Große Datenmengen sind von Natur aus oft unübersichtlich. Mit Gnuplot verdeutlichen Sie Zusammenhänge.
Gnuplot ist ein kompaktes Tool zum grafischen Aufbereiten komplexer und großer Datenmengen – in etwa so wie der Datenpilot in OpenOffice Calc. Es ist in der Lage, Daten in viele verschiedene Formate zu plotten, arbeitet allerdings nur auf der Kommandozeile.
Verschiedene Situationen (Bevölkerungswachstum, COVID-19, Belegung der Intensivbetten) zeigen, wie Sie Gnuplot dazu nutzen, Zahlenmaterial auszuwerten und optisch ansprechend aufzubereiten. Das gelingt sowohl in Form von 2D- als auch 3D-Graphen. Selbst Funktionen mit Formeln sind mit dem Programm möglich.
Helmut Schmidt hat zu Lebzeiten in einer Talkshow die Aussage gemacht, dass die “Weltbevölkerung explodiert, die Erde aber nicht größer wird.” Über die Probleme, die dadurch entstehen, wolle er gar nicht weiter nachdenken. Den meisten Menschen ist diese Tatsache lediglich verschwommen bewusst. Das Auswerten und Anzeigen der Bevölkerungswachstumszahlen in einzelnen Ländern dient also als erstes Fallbeispiel zum Auswerten und Anzeigen.
Superschnelles Intro
Um zu verstehen, wie Gnuplot arbeitet, geben Sie die Kommandos aus Listing 1 in ein Terminal ein. Auf diese Weise erzeugen Sie zwei PNG-Grafik-Dateien, von denen die eine die Daten in 2D und die andere in 3D anzeigt. Beide haben jeweils eine X- und eine Y-Achse, die 3D-Grafik zusätzlich eine Z-Achse (Abbildung 1).
Listing 1
Einfach Grafiken erzeugen
paste <(seq 10) <(seq 10) | gnuplot -e 'set terminal png size 800,600; plot "-" with lines' > 2d.png paste <(seq 10) <(seq 1 2 20) <(seq 10) | gnuplot -e 'set terminal png size 800,600; splot "-" with lines' > 3d.png

Abbildung 1: Einfache Plots in 2D- und die 3D-Ansicht haben Sie mit je einem einzigen Befehl erstellt.
Bei Bedarf geben Sie explizit mit using an, welche Spalten Sie genau plotten möchten. Das wäre für die erste Anweisung using 1:2 und für die zweite Anweisung using 1:2:3, was im ersten Fall bedeutet, dass es nur zwei Spalten gäbe, im zweiten Fall eine zusätzliche Spalte für die Z-Achse.
Gnuplot hat eine gewisse Ähnlichkeit mit einer ganz normalen Shell wie Bash, Dash, Zsh oder Sh. Aber das Endprodukt sind Grafiken. Wenn Sie das Tool ohne Argumente starten, haben Sie einen Prompt vor sich, an dem Sie Befehle eingeben und mit programmatischen Konstrukten wie If, For und Ähnliches arbeiten dürfen (siehe Kasten “Am Prompt”). In vielen Fällen ist es aber einfacher, mit Gnuplot-Skripten zu arbeiten, anstatt alles in eine Pipe zu packen.
Am Prompt
Starten Sie das Programm ohne Parameter, haben Sie die Möglichkeit, Befehle direkt einzugeben und bei jedem Befehl anzuschauen, was genau passiert. Sofern Sie Befehl für Befehl richtig eingeben, führt Gnuplot stillschweigend die Kommandos aus.
Geben Sie eines falsch ein, erhalten Sie eine hilfreiche Fehlermeldung. Vorherige Anweisungen gehen aber nicht verloren, weil Sie etwas falsch eingetippt haben. Haben Sie einmal mit set title einen Titel gesetzt, bleibt dieser Wert erhalten, bis Sie ihn wieder überschreiben.
Das Hilfssystem von Gnuplot ist sehr einfach: Sie geben am Prompt help ? ein, um eine Liste von Themen zu erhalten. Wollen Sie mehr über das Setzen des Titels erfahren, geben Sie etwa help title ein.
Haben Sie schon etwas mehr Erfahrung mit einigen Kommandos, reicht es aus help Anfangsbuchstabe einzugeben, um alle Anweisungen mit einem bestimmten Anfangsbuchstaben aufgelistet zu bekommen. Das mag am Anfang etwas komplex aussehen, ist aber mit der Zeit oft sehr einfach.
Daten-Fenster
CSV-Daten sind ein ausgezeichnetes Ausgangsmaterial für die Arbeit mit Gnuplot. Dabei geben Sie den Trenner (meist ein Komma) für Spalten an. Wie Sie gesehen haben, benötigt das Programm im Fall von 2D-Grafiken mindestens zwei und im Fall von 3D-Grafiken mindestens drei Spalten, die entweder numerische Daten, zeitliche Angaben oder Strings enthalten dürfen.
Die erste Zeile einer CSV-Datei enthält oft die Namen der Spalten. Gibt es viele Spalten, greifen Sie effizienter über diesen Namen auf die Daten zu. Statt using 4:33 nutzen Sie dann using "spalte_datum":"spalte_spezielle_auwahl" als Anweisung.
In CSV-Dateien stehen die Datenblöcke nach rechts hintereinander. Die Blöcke, die für Sie interessant sind, filtern Sie anhand der ersten Zeile heraus. Um das auszuprobieren, laden Sie sich die Bevölkerungsdaten als Beispiel herunter [1].
Diese Website enthält statistisches Material bezüglich der Bevölkerung in einzelnen Ländern. Zusätzlich finden Sie darin in verschiedenen Varianten Prognosen für die Bevölkerungsentwicklung. Wenn Sie den Befehl aus Listing 2, Zeile 1 eingeben, erhalten Sie Informationen über die Spalten.
Listing 2
Spaltennamen extrahieren
$ sed 's/,/\n/g;1q' WPP2019_TotalPopulationBySex.csv | nl
1 LocID
2 Location
3 VarID
4 Variant
5 Time
6 MidPeriod
7 PopMale
8 PopFemale
9 PopTotal
10 PopDensity
In diesem Fall sind das die Spalten 2, 4 und 5, also Location,Variant und Time, die im Beispiel eine Rolle spielen. Wollen Sie alle Varianten im Überblick sehen, nutzen Sie den Befehl aus Listing 3, Zeile 1. Die darauffolgenden Zeilen zeigen die Ausgabe.
Listing 3
Variantendaten extrahieren
$ gawk -F "," '{print $4}' WPP2019_TotalPopulationBySex.csv | sort | uniq | sed -r '/^[0-9]+/d' | nl
1 Constant fertility
2 Constant mortality
3 High
4 Instant replacement
5 Low
6 Lower 80 PI
7 Lower 95 PI
8 Median PI
9 Mediterranean and South China Sea (AIMS)"
10 Medium
11 Momentum
12 No change
13 Upper 80 PI
14 Upper 95 PI
15 Variant
16 Zero migration
In Zeile 9 fällt auf, dass die Daten etwas unsauber eingerückt sind. Falls Sie also Daten mit Grep für bestimmte Länder filtern wollen, sollten Sie aufpassen, was Sie genau erwischen und was nicht. Im Beispiel dient das Skript aus Listing 4 dazu, einzelne Länder mit der Variante Medium herauszufiltern.
Listing 4
Daten mittels Shell-Skript filtern
#!/usr/bin/bash
datei="WPP2019_TotalPopulationBySex.csv"
for land in Germany Belgium Sweden
do
(head -n 1 $datei; grep -E "$land.+Medium," $datei) > ${land}.csv
done
Sie haben nun Zahlen zur Bevölkerungsentwicklung der Länder Deutschland, Schweden und Belgien in drei verschiedene CSV-Dateien separiert. Die Dateien Germany.csv, Belgium.csv, und Sweden.csv sind nicht umfangreich, bei Bedarf werfen Sie mit Cat oder Less einen Blick auf die Daten.
Um die so gefilterten Blöcke mit Gnuplot umzusetzen, würde sich das Skript aus Listing 5 eignen. Grundlegende Einstellungen legen Sie über den Set-Befehl fest. In den ersten sechs Zeilen definieren Sie so Feldtrenner, die Ausgabe in PNG, das Format der Y-Achse, die Ticks der X-Achse und regeln die Abstände für links und unten. In den Zeilen 8 bis 10 sind die Linien-Typen definiert oder besser gesagt: Sie überschreiben hier die Standardwerte.
Listing 5
Bevölkerungsdaten auswerten
set datafile separator ","
set term png size 1000, 700
set format y "%.0f"
set xtics 15
set lmargin 10
set bmargin 2
set linetype 1 lw 2.8 pt 1 lc rgb "black"
set linetype 2 lw 1.4 pt 2 lc rgb "mediumpurple3"
set linetype 3 lw 1.8 pt 4 lc rgb "dark-blue"
deu="Germany.csv"
swe="Sweden.csv"
bel="Belgium.csv"
time="Time"
male="PopMale"
female="PopFemale"
population="PopTotal"
density="PopDensity"
set title "Entwicklung der Bevölkerungsdichte in Deutschland"
set output "png/deutschland_bevölkerungsdichte.png"
plot "Germany.csv" using time:density with boxes title "Bevölkerungsdichte Deutschland" lt rgb "green"
set title "Bevölkerungsdichte Deutschland/Schweden im Vergleich"
set output "png/deutschland_schweden_bevölkerungsdichte.png"
plot "Germany.csv" using time:density with boxes title "Deutschland" lt rgb "green" lw 0.8,\
"Sweden.csv" using time:density with boxes title "Schweden" lt rgb "olive" lw 1.4
do for [land in "Germany Sweden Belgium"]{
set title "Bevölkerungsstatistiken ".land
set output "png/".land.".png"
plot land.".csv" using time:(column(population)*1000) with lines title "Bevölkerung insgesamt" lt 1,\
land.".csv" using time:(column(female)*1000) with lines title "weiblicher Anteil" lt 2,\
land.".csv" using time:(column(male)*1000) with lines title "männlicher Anteil" lt 3
}
In den Zeilen 12 bis 20 finden Sie Variablen-Deklarationen für die CSV-Dateien und einige Spaltennamen, die die Software dann plottet. Danach setzt das Skript den Titel und das Ziel für die auszugebende Datei, direkt im Anschluss folgt ein erster Plot-Befehl, der die Datei Germany.csv mit den Spalten Time:PopDensity plottet (Abbildung 2). Den Vorgang starten Sie dann schließlich mit gnuplot populus.pl.

Abbildung 2: Wenn Sie nur wenige Daten auswerten, besteht kaum eine Möglichkeit, etwas falsch zu machen. Das Ergebnis bleibt in jedem Fall übersichtlich.
Es ergibt Sinn, ein Verzeichnis anzulegen, in das Sie hineinplotten, da rein technisch mit Gnuplot die Arbeit wie am Fließband möglich wäre. Wenn Sie ein Verzeichnis für die Ergebnisse nutzen, ist es wichtig, dass dieses schon existiert, da Sie sonst eine Fehlermeldung erhalten.
Als Nächstes erstellt das Skript einen Plot über die Bevölkerungsdichte von Deutschland und Schweden im Vergleich, wobei die Daten von Sweden.csv und Germany.csv in einem Diagramm zusammen erscheinen (Abbildung 3). In den Zeilen 32 bis 38 sehen Sie, wie Sie verschiedene Daten in einer For-Schleife abarbeiten.

Abbildung 3: Wollen Sie zwei verschiedene Datensätze in 2D darstellen, ist es eventuell nötig, mit den Farben etwas zu experimentieren, damit das Ergebnis gut und übersichtlich aussieht.
In dieser Schleife sind Deutschland, Schweden und Belgien Objekt der Betrachtung, und Sie erstellen auf diesem Weg drei Dateien. Dieses Skript erzeugt also fünf Dateien, die bei recht minimalem Aufwand ansprechende Grafiken enthalten.
Wollen Sie zahlreiche Datenstränge darstellen, lohnt ein Blick auf die 3D-Varianten. Im nächsten Beispiel, das sich mit Statistiken bezüglich der Corona-Pandemie von Our World in Data beschäftigt, sehen Sie die 3D-Funktionen im Einsatz, wenn es darum geht, die Daten mehrerer Länder parallel anzuzeigen.
SARS-CoV-2 in 3D
Um dieses kleine Projekt anzugehen, laden Sie sich die Datei herunter [2]. Die Daten der einzelnen Länder sind in Blöcken organisiert, ein kleines Skript hilft Ihnen beim Splitten (Listing 6).
Listing 6
Daten extrahieren
#!/usr/bin/bash
for land in Germany Belgium "United States" Sweden
do
(head -n 1 owid-covid-data.csv; grep -F $land owid-covid-data.csv) > ${land}.csv
done
Listing 7 enthält ein Skript, das die extrahierten Dateien weiter verarbeitet. Die ersten acht Zeilen deklarieren wieder grundlegende Parameter, darunter, dass in der X-Achse das Datums-Format zum Tragen kommt und welchen Zeitraum Sie genau verarbeiten wollen (Zeile 8).
Listing 7
Daten zur Corona-Pandemie aufbereiten
set datafile separator ","
set timefmt "%Y-%m-%d"
set term png size 1200, 850 background rgb "light-gray"
set view 75, 45, 1.2, 1.2
set lmargin 10
set bmargin 3
set xdata time
set xrange ["2021-03-01":"2021-06-13"]
set linetype 1 lw 1.9 pt 1 lc rgb "web-blue"
set linetype 2 lw 1.2 pt 2 lc rgb "orange-red"
set linetype 3 lw 1.2 pt 3 lc rgb "dark-goldenrod"
set linetype 4 lw 1.2 pt 4 lc rgb "dark-magenta"
ger="Germany.csv"
swe="Sweden.csv"
bel="Belgium.csv"
usa="United States.csv"
ncpm="new_cases_per_million"
rr="reproduction_rate"
set title "Ländervergleich Deutschland - Schweden - Belgien - United States" tc rgb "midnight-blue" font "sans,15" offset -10,0
set output "png/new_cases_per_million.png"
splot ger using 4:(10):ncpm with linesp title "Deutschland: Neue Fälle pro Millionen" lt 1,\
swe using 4:(20):ncpm with linesp title "Schweden: Neue Fälle pro Millionen" lt 2,\
bel using 4:(30):ncpm with linesp title "Belgien: Neue Fälle pro Millionen" lt 3,\
usa using 4:(40):ncpm with linesp title "Usa: Neue Fälle pro Millionen" lt 4
set output "png/reproduction_rate.png"
splot ger using 4:(10):rr with linesp title "Deutschland: Reproduktionsrate" lt 1,\
swe using 4:(20):rr with linesp title "Schweden: Reproduktionsrate" lt 2,\
bel using 4:(30):rr with linesp title "Belgien: Reproduktionsrate" lt 3,\
usa using 4:(40):rr with linesp title "Usa: Reproduktionsrate" lt 4
array daten[1000000]
world_data=system('(head -n 1 owid-covid-data.csv;grep -F World owid-covid-data.csv)')
index=1
do for [w in world_data ] {
daten[index]=w
index=index+1
}
set title "Corona Virus weltweit (hoffentlich) im Abflug" tc rgb "midnight-blue" font "sans,15" offset -10,0
set output "png/reproduction_rate_world.png";set term png size 800, 480 background rgb "light-gray"
plot daten using 4:rr with histeps title "Reproduktionsrate der ganzen Welt"
In den Zeilen 9 bis 13 überschreiben Sie schon in Gnuplot enthaltene Linientypen. Danach folgen grundlegende Deklarationen für die zuvor erstellten CSV-Dateien und die Spalten, die die Software im Folgenden innerhalb des Plots anspricht (Abbildung 4).

Abbildung 4: Hier sehen Sie vier Länder im Vergleich in der 3D-Darstellung. Würden Sie dies als 2D-Grafik aufbauen, wäre optisch nicht so einfach zu erfassen, wie die Entwicklung in den einzelnen Ländern ist.
In den Zeilen 25 bis 35 sehen Sie, wie Sie mit dem Splot-Befehl für die 3D-Darstellung arbeiten, wenn Sie für die Z-Achse keine Daten zur Hand haben. Die Z-Achse dient oftmals nur zum Anordnen der einzelnen Daten innerhalb des 3D-Raums, sodass Sie diese einfach statisch in den Datensatz eintragen (Listing 8).
Listing 8
Beispiele mit statischen Z-Werten
splot "Name" using "X-Spalte":(10):"Y-Spalte" # vorne splot "Name" using "X-Spalte":(20):"Y-Spalte" # hinten
Wie Sie sehen, ist es nicht schwer, von 2D auf 3D zu wechseln, selbst wenn die Daten für die Z-Achse fehlen. Es kommt ganz auf die Daten, Situation oder das Publikum an, ob eine 2D- oder 3D-Ansicht mehr Sinn ergibt. 3D-Grafiken bringen in der Regel keine Vorteile, wenn es nur einen Datenstrang gibt (Abbildung 5).

Abbildung 5: Liegen nur wenige Datenstränge vor, ist es meist besser, bei 2D-Ansichten zu bleiben. Sie brauchen aber nicht nur einfache Linien zu verwenden, probieren Sie doch mit histeps etwas Neues aus.
Folgen Sie weiter dem Skript, sehen Sie, wie Sie in Gnuplot mit For-Schleifen und Arrays arbeiten (Zeilen 38 bis 44). Wenn Sie mit so etwas arbeiten, ist es buchstäblich kein Problem, anschauliche Diagramme und Grafiken am laufenden Band zu erstellen. Im Prinzip wäre es möglich, aus einem Gnuplot-Skript heraus mit dem System-Befehl alle Länder in einem Rutsch zu plotten, wenn Sie Profi mit der Bash oder einer anderen Kommandozeile sind.
Gnuplot leistet aber auch gute Dienste beim Filtern von Daten. Manchmal sind diese auf unintuitive Weise angeordnet. Dann filtern Sie in Gnuplot heraus, was Sie brauchen oder nicht brauchen. Das ist im Prinzip so, als würden Sie die Daten als Matrix betrachten und einzelne Stücke herausschneiden. Wie das funktioniert, sehen Sie im nächsten Beispiel.
Gnuplot goes Matrix
Für dieses Projekt laden Sie sich die Daten zur Krankenhausbelegung herunter [3]. Die Datei besteht aus reinem Text, bei Bedarf werfen Sie mit einem Editor einen Blick hinein. Tun Sie das, sehen Sie, dass darin Daten bezüglich der Belegung nach den einzelnen Bundesländer geordnet enthalten sind, also ein Block von 17 Zeilen. Am Ende stehen die Daten von ganz Deutschland.
Wollen Sie nur auf die Daten eines Bundeslands zurückgreifen, wählen Sie jeweils ab einer bestimmten Zeile die Daten in einem Intervall von 17. Für solche Fälle bringt Gnuplot die Funktion every mit.
Dieses Schlüsselwort arbeitet so ähnlich wie die Using-Anweisung mit dem Unterschied, dass Sie umfassender und spezifischer angeben dürfen, welche Reihen und Spalten Sie einschließen wollen (Listing 9).
Listing 9
Abstrakte Angabe für every
Spalten_Inkrement:Reihen_Inkrement:Start_Spalte:Start_Reihe:End_Spalte:End_Reihe
In Listing 10 sehen Sie, wie der Einsatz von every und using in der Praxis aussieht. Das Ergebnis ist eine 3D-Grafik, weil diese in diesem Fall übersichtlicher ist und mehrere Datenstränge parallel anzeigt (Abbildung 6).
Listing 10
Beispiel Auslastung Krankenhausbetten
#!/usr/bin/gnuplot datei="bundesland-zeitreihe.csv" set terminal png size 1500,800 set output "intensivbetten.png" set datafile separator "," set timefmt "%Y-%m-%dT%H:%M:%S+02:00" set xdata time set view 65, 55, 1.0, 1.0; set margin 2 set title "Krankenhausbettenbelegung - einige Bundesländer in Relation zu Deutschland" splot datei every 17::17::7000 using 1:(400):5 with filledcurves title "DEUTSCHLAND",\ datei every 17::7::7000 using 1:(300):5 with filledcurves title "THUERINGEN",\ datei every 17::13::7000 using 1:(200):5 with filledcurves title "BAYERN",\ datei every 17::2::7000 using 1:(100):5 with filledcurves title "NORDRHEIN WESTFALEN",\ datei every 17::5::7000 using 1:(0):5 with filledcurves title "RHEINLAND PFALZ"

Abbildung 6: Hier bietet sich wieder die 3D-Darstellung an. Da im Beispiel der Einsatz von every möglich war, hielt sich der Aufwand und der Umfang des Skripts in Grenzen.
Zudem ist es ein Skript, das Sie wie eine ausführbare Datei starten. Sie brauchen nur den passenden Interpreter, in diesem Fall Gnuplot, in der ersten Zeile einzufügen. In Zeile 11 sehen Sie eine Anweisung, die die 3D-Ansicht ausrichtet und einen Rand für die bessere Optik der ganzen Grafik setzt.
In den Zeilen 15 bis 19 steht der eigentliche Plot-Befehl. Da es in der Datei eigentlich keine Werte für die Z-Achse gibt, sind diese wieder einfach gesetzt und in der Mitte der Werte für den Using-Befehl zwischen Klammern eingeschlossen als Ausdruck angegeben. In diesem Fall rücken die Werte für Deutschland durch die 400 für die Z-Achse ganz nach hinten.
Die Werte der Bundesländer rücken dagegen in den Vordergrund der Grafik. Mit diesen Werten ist es leicht, etwas auszuprobieren und zum Beispiel die Kurve von Deutschland noch weiter in den Hintergrund zu rücken, indem Sie einfach den Wert erhöhen.
Es ist darüber hinaus möglich, komplexe Funktionen mit Gnuplot zu realisieren, indem Sie in Funktionen mit dem Ternary-Operator (a > 10 ? a : a+2) arbeiten und diese Operationen schachteln. So bilden Sie selbst komplexe Funktionen aus der Wirtschaft oder dem Einkommenssteuerrecht, wie etwa die Einkommenssteuerformel ab und gehen vielleicht als nächste Herausforderung eine grafische Brutto-Netto-Analyse an, um kompakt zu sehen, wie sich die Einkommenssteuer bei einer bestimmten Gehaltsstufe verhält.
Fazit
Die Beispiele zeigen, was für ein leistungsfähiges Werkzeug Gnuplot ist, um Datenberge verschiedenen Formats mit geringem Aufwand anschaulich zu visualisieren. Dabei ist es möglich, die Software flexibel in andere Projekte oder einfach innerhalb der Kommandozeile, etwa am Ende einer Pipe, zu integrieren.
Haben Sie die Software einmal im Griff, stellen Sie vermutlich schnell fest, dass die Syntax recht einfach ist und schnell zu Ergebnissen führt. Im Gegensatz zu anderen Shells ist das Endprodukt eben ein Plot. Ansonsten stehen Variablen, Schleifen, Arrays, If-Verzweigungen und Ähnliches bereit. Mit zunehmender Praxis ist es dann sehr angenehm grafische Outputs von Daten zu erstellen.
Sie haben gesehen, wie einfach es ist, Statistiken verschiedener Bereiche professionell darzustellen, um einen sehr genauen Einblick in Daten zu bekommen. Beherrschen Sie das Visualisieren, verstehen Sie Daten in jedem Fall besser, als wenn Sie die reinen Zahlen betrachten. (agr)





