# Datenvisualisierung mit¶

Als erstes: IPython interaktiv machen:

In [1]:

    %matplotlib inline
    # bei euch: %matplotlib (nur in iPython)

Um mit Matplotlib arbeiten zu können, muss die Bibliothek erst einmal importiert werden. Damit wir nicht so viel tippen müssen geben wir ihr einen kürzeren Namen:

In [2]:

    import matplotlib.pyplot as plt
    plt.rcParams['figure.figsize'] = (10, 8)
    plt.rcParams['font.size'] = 16
    plt.rcParams['lines.linewidth'] = 2

Außerdem brauchen wir ein paar Funktion aus `numpy`, die euch schon bekannt sind

In [3]:

    import numpy as np

Ein einfaches Beispiel: $f(x)=x^2$

In [4]:

    x = np.linspace(0, 1) # gibt 50 Zahlen in gleichmäßigem Abstand von 0–1
    plt.plot(x, x**2)
    # Falls nicht interaktiv:
    # plt.show()

Out[4]:

    [<matplotlib.lines.Line2D at 0x7f2ab0751670>]

Anderes Beispiel: $\sin(t)$ mit verschiedenen Stilen. Vorsicht, die Funktionen und $\pi$ sind Bestandteil von `numpy`

In [5]:

    t = np.linspace(0, 2 * np.pi)
    plt.plot(t, np.sin(t))

Out[5]:

    [<matplotlib.lines.Line2D at 0x7f2aa0f1cf70>]

In [6]:

    plt.plot(t, np.sin(t), 'r--')

Out[6]:

    [<matplotlib.lines.Line2D at 0x7f2aa0ea1310>]

In [7]:

    plt.plot(t, np.sin(t), 'go')

Out[7]:

    [<matplotlib.lines.Line2D at 0x7f2aa0e84fa0>]

Tabelle mit allen Farben und Styles: matplotlib.axes.Axes.plot

Neue Grenzen mit `xlim(a, b)` und `ylim(a, b)`

In [8]:

    plt.plot(t, np.sin(t))
    plt.xlim(0, 2 * np.pi)
    plt.ylim(-1.2, 1.2)

Out[8]:

    (-1.2, 1.2)

## Es fehlt noch etwas...¶

In [9]:

    with plt.xkcd():
        plt.title('Axes with labels')
        plt.plot(t, np.sin(t))
        plt.xlabel('t / s')
        plt.ylabel('U / V')
        plt.ylim(-1.1, 1.1)
        plt.xlim(0, 2 * np.pi)

Achsen-Beschriftungen können mit LaTeX-Code erstellt werden → LaTeX-Kurs in der nächsten Woche.

In [10]:

    plt.plot(t, np.sin(t))
    plt.xlabel(r'$t / \mathrm{s}$')
    plt.ylabel(r'$U / \mathrm{V}$')

Out[10]:

    Text(0, 0.5, '$U / \\mathrm{V}$')

## Einheiten in Achsenbeschriftungen werden wegdividiert:¶

In [11]:

    plt.plot(t, np.sin(t))
    plt.xlabel(r'$t / \mathrm{s}$')
    plt.ylabel(r'$U \,/\, \mathrm{V}$')  # Spaces sind Geschmacksfrage……

Out[11]:

    Text(0, 0.5, '$U \\,/\\, \\mathrm{V}$')

Mehr zu Einheiten gibt es im LaTeX-Kurs.

## Legende¶

Legenden für Objekte die ein `label` tragen

In [12]:

    plt.plot(t, np.sin(t), label=r'$\sin(t)$')
    plt.legend()
    #plt.legend(loc='lower left')
    #plt.legend(loc='best')

Out[12]:

    <matplotlib.legend.Legend at 0x7f2aa0cabeb0>

Seit matplotlib 2.0.2 ist `loc=best` standardmäßig eingestellt.

Andere möglche Orte für die Legende findest du hier:

https://matplotlib.org/api/legend_api.html

### Gitter¶

Mit `grid()` wird ein Gitter erstellt:

In [13]:

    plt.plot(t, np.sin(t))
    plt.grid()

## Laden von Daten¶

In [14]:

    x, y = np.genfromtxt('data/example_data_linear.txt', unpack=True)
    plt.plot(x, y, 'k.')

    t = np.linspace(0, 10)
    plt.plot(t, 5 * t, 'r-')

Out[14]:

    [<matplotlib.lines.Line2D at 0x7f2aa0b6d1f0>]

## Auslagern in ein Skript¶

Speichert den folgenden Code in eine Textdatei `plot.py` ab.

Öffnet ein Terminal und startet das Programm:

    python plot.py

In [15]:

    import matplotlib.pyplot as plt
    import numpy as np

    x = np.linspace(0, 1)
    plt.plot(x, x**2, 'b-')
    plt.savefig('plot.pdf')

Mit `savefig` speichert man die Abbildung.

In diesem Fall sollte die Datei `plot.pdf` erstellt worden sein.

Es gibt viele Ausgabeformate: `pdf`, `png`, `svg`, LaTeX

Um mehrere Plots zu speichern kann man `plt.clf()` verwenden. Der Befehl leert die aktuelle figure und steht für `clear figure`.

In [16]:

    import matplotlib.pyplot as plt
    import numpy as np

    x = np.linspace(0, 1)

    ### Plot 1
    plt.clf()

    plt.plot(x, x**2, 'b-',label='Plot 1')
    plt.legend()
    plt.savefig('plot_1.pdf')

    ### Plot 2
    plt.clf()

    plt.plot(x, x**3, 'r-')
    plt.savefig('plot_2.pdf')

## Komplexere Abbildungen¶

Natürlich kann man mehrere Linien in einen Plot packen:

In [17]:

    x = np.linspace(0, 1)

    plt.plot(x, x**2, label=r'$x^2$')
    plt.plot(x, x**4)
    plt.plot(x, x**6, 'o', label=r'$x^6$')

    plt.legend()

Out[17]:

    <matplotlib.legend.Legend at 0x7f2aa0a37610>

Es werden nur die Plots in der Legende angezeigt, die ein Label haben.

Man kann auch mehrere Plots in ein Bild packen:

In [18]:

    x = np.linspace(0, 2 * np.pi)

    # #rows, #columns, plot index = row * (#cols) + col
    plt.subplot(2, 1, 1)
    plt.plot(x, x**2)
    plt.xlim(0, 2 * np.pi)

    plt.subplot(2, 1, 2)
    plt.plot(x, np.sin(x))
    plt.xlim(0, 2 * np.pi)

Out[18]:

    (0.0, 6.283185307179586)

Dies führt manchmal zu Spacing-Problemen und Teilen die sich überscheneiden, Lösung: `plt.tight_layout()`

In [19]:

    x = np.linspace(0, 2 * np.pi)

    # Anzahl Zeile, Anzahl Spalten, Nummer des Plots
    plt.subplot(2, 1, 1)
    plt.plot(x, x**2)
    plt.xlim(0, 2 * np.pi)
    plt.title(r"$f(x)=x^2$")

    plt.subplot(2, 1, 2)
    plt.plot(x, np.sin(x))
    plt.xlim(0, 2 * np.pi)
    plt.title(r"$f(x)=\sin(x)$")

    plt.tight_layout()

Plot im Plot:

In [20]:

    plt.plot(x, x**2)

    # Koordinaten relativ zum Plot (0,0) links unten (1,1) rechts oben
    plt.axes([0.2, 0.45, 0.3, 0.3])

    # [x-location, y-location, x-length, y-length]

    plt.plot(x, x**3)

Out[20]:

    [<matplotlib.lines.Line2D at 0x7f2aa0925280>]

## Plots mit Fehlerbalken¶

Sehr häufig werden im Praktikum Plots mit Fehlerbalken benötigt:

In [21]:

    rng = np.random.default_rng()
    x = np.linspace(0, 2 * np.pi, 10)
    errX = 0.4 * rng.standard_normal(10)
    errY = 0.4 * rng.standard_normal(10)

    plt.errorbar(x + errX, x + errY, xerr=0.4, yerr=errY, fmt='o')

Out[21]:

    <ErrorbarContainer object of 3 artists>

## Achsen-Skalierung¶

Logarithmische (oder auch andere) Skalierung der Achsen ist auch möglich:

In [22]:

    x = np.linspace(0, 10)

    plt.plot(x, np.exp(-x))
    plt.yscale('log')
    #plt.xscale('log')

## Polar-Plot¶

Manchmal braucht man einen Polarplot:

In [23]:

    #r = np.linspace(0, 10, 1000)
    r = np.linspace(0, 10, 50)
    theta = 2 * np.pi * r

    plt.polar(theta, r)

Out[23]:

    [<matplotlib.lines.Line2D at 0x7f2aa070ae20>]

# Ticks¶

Man kann sehr viele Sachen mit Ticks machen…

In [24]:

    x = np.linspace(0, 2 * np.pi)

    plt.plot(x, np.sin(x))
    plt.xlim(0, 2 * np.pi)
    # erste Liste: Tick-Positionen, zweite Liste: Tick-Beschriftung
    plt.xticks([0, np.pi / 2, np.pi, 3 * np.pi / 2, 2 * np.pi],
               [r"$0$", r"$\frac{1}{4}\tau$", r"$\frac{1}{2}\tau$", r"$\frac{3}{4}\tau$", r"$\tau$"])
    plt.title(r"$\tau$ FTW!")

Out[24]:

    Text(0.5, 1.0, '$\\tau$ FTW!')

In [25]:

    rng = np.random.default_rng()
    months = ['January',
              'February',
              'March',
              'April',
              'May',
              'June',
              'July',
              'August',
              'September',
              'October',
              'November',
              'December']

    plt.plot(np.arange(12), rng.random(12))
    plt.xticks(np.arange(12), months, rotation=45, rotation_mode='anchor', ha='right', va='top')
    plt.xlim(0, 11)

Out[25]:

    (0.0, 11.0)

# Histogramme¶

Sehr häufig braucht man Histogramme.

In [26]:

    # Zufallsdaten generieren:
    rng = np.random.default_rng()
    x = rng.normal(0, 1, 1000)
    plt.hist(x)
    # try histtype='stepfilled'

Out[26]:

    (array([  2.,  24.,  84., 154., 218., 269., 161.,  61.,  23.,   4.]),
     array([-3.18895607, -2.53910277, -1.88924948, -1.23939619, -0.5895429 ,
             0.06031039,  0.71016369,  1.36001698,  2.00987027,  2.65972356,
             3.30957685]),
     <BarContainer object of 10 artists>)

# Objektorientiertes Plotten¶

Bis jetzt haben wir die schnelle Variante mit der `pyplot`-Syntax benutzt. Wenn man viele Plots anlegt, ist der objekt-orientierte Ansatz für matplotlib besser geeignet.

In [27]:

    import matplotlib.pyplot as plt
    import numpy as np

    t = np.linspace(0, 2*np.pi, 1000)

    fig, (ax1, ax2) = plt.subplots(2, 1)

    ax1.plot(t, np.sin(t), 'r-')
    ax1.set_title(r"$f(t)=\sin(t)$")
    ax1.set_xlabel("$t$")
    ax1.set_xlim(0, 2 * np.pi)
    ax1.set_ylim(-1.1, 1.1)

    ax2.plot(t, np.cos(t), 'b-')
    ax2.set_title(r"$f(t)=\cos(t)$")
    ax2.set_xlabel("$t$")
    ax2.set_xlim(0, 2 * np.pi)
    ax2.set_ylim(-1.1, 1.1)

    fig.tight_layout()

# 3D Plots¶

In [28]:

    from mpl_toolkits.mplot3d import Axes3D

    fig = plt.figure()
    ax = fig.add_subplot(projection='3d')

    theta = np.linspace(-4 * np.pi, 4 * np.pi, 200)
    z = np.linspace(-2, 2, 200)

    r = z**2 + 1
    x = r * np.sin(theta)
    y = r * np.cos(theta)

    ax.plot(x, y, z, label='parametric curve')
    ax.legend()

    plt.show()

Weitere Beispiele zum 3dim Plotten findet ihr hier:

https://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html

# LaTeX

Es ist auch möglich LaTeX für das Setzen aller Plot-Beschriftungen (d.h. Achsenbeschriftungen, Ticks, Legenden, usw.) zu verwenden. Seht Euch dazu die "TeX in matplotlib" Folien an.