Grafische Ausgaben

Es gibt sehr viele Varianten für die grafische Ausgabe von Zahlenwerten. Im folgenden wird die Bibliothek mathplotlib verwendet. In der Regel funktionieren die Beispiele nicht über den Button "Python Online", weshalb dieser hier nicht zu sehen ist. Die Beispiele sollten daher über den Button "Copy" kopiert werden und in der eigenen grafischen Umgebung idle3, Thonny, etc., ausgeführt werden.

Erste Versuche

Einführung in matplotlib


# Hinweis
# ------- file: myplot.py ------
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)

plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x))

plt.show()

# Hinweis
import numpy as np
import matplotlib.pyplot as plt

def make_plot(p, num_pts=40):
  k = np.arange(num_pts)    # [ 0 1 2 3 ... num_pts-1 ]
  z = (1 - 1/p)**k          # [ z0 z1 z2 ... znum_pts-1 ]
  plt.axes().set_aspect(1)
  plt.plot(z.real, z.imag)
  plt.grid()
  plt.title(f"$x^{{ {p.real} + {p.imag}i }}$")
  plt.show()

make_plot(0.53 + 0.4j)
make_plot(0.50 + 0.3j,100)
make_plot(0.48 + 0.3j,100)

# Hinweis
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(121)

fig, ax = plt.subplots()

def histoPlot(ax):
    ax.hist(np.random.normal(0, 1, 1000), bins=100)

histoPlot(ax)
histoPlot(ax)
histoPlot(ax)
plt.show()

# Hinweis
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

def getdata():
    return np.random.uniform(0,1,10)

fig, axe = plt.subplots(5, 2)
row=[0,0,1,1,2,2,3,3,4,4]
col=[0,1,0,1,0,1,0,1,0,1]
for im in range(10):
    r=row[im]
    c=col[im]
    axe[r][c].scatter(getdata(), getdata())

# trial 1 -> tried and it works, no need for trial 2
plt.show()
plt.savefig('figure1.pdf')

Einführung in matplotlib

Das Prinzip

Sehr häufig müssen einfache oder auch komplexe mathematische Funktionen der Art $y=f(x)$ dargestellt werden. In matplotlib wird zuerst die Variable graph als eine Instanz der Klasse plt.figure erstellt. Sie kann als Container für alle folgenden Objekte, die zum Graphen gehören, betrachtet werden. Die üblichen Achsen als eine Instanz der Klasse plt.axes definieren die sogenannte Bounding Box, sowie die "ticks" und "label" der Achsen. Nach Festlegung der Achsen kann mit ax.plot eine Funktion graphisch dargestellt werden.

# Hinweis
import matplotlib.pyplot as plt
import numpy as np

graph = plt.figure()
achsen = plt.axes()

x = np.linspace(0, 10, 1000)
achsen.plot(x, np.sin(x));

Die folgende Abbildung zeigt die sogenannte Schwebung, die man beim Stimmen von zwei gleichen Instrumenten benutzen kann.

# Hinweis
import matplotlib.pyplot as plt
import numpy as np

graph = plt.figure()
achsen = plt.axes()

x = np.linspace(0, 40*np.pi, 3000)
achsen.plot(x, np.sin(x)+np.sin(1.1*x));

Es können beliebig viele Funktionen in ein und dasselbe Koordinatensystem eingetragen werden:

# Hinweis
import matplotlib.pyplot as plt
import numpy as np

graph = plt.figure()
achsen = plt.axes()

x = np.linspace(0, 40*np.pi, 3000)
achsen.plot(x, np.sin(x)+np.sin(1.1*x));
achsen.plot(x, np.sin(x)+np.sin(1.05*x));
plt.show()

Optionen

Farbe und Linienstil

Zu den üblichen Einstellungen gehören Linienfarben und -stile, was über zusätzliche Argumente von plt.plot(...) erfolgt. Für die Farbe das Schlüsselwort color, verschiedene Farbdefinitionen möglich sind.

:
# Hinweis
import matplotlib.pyplot as plt
import numpy as np

graph = plt.figure()
achsen = plt.axes()

x = np.linspace(0, 40*np.pi, 3000)
achsen.plot(x, np.sin(x - 0), color='blue')        # specify color by name
achsen.plot(x, np.sin(x - 1), color='g')           # short color code (rgbcmyk)
achsen.plot(x, np.sin(x - 2), color='0.75')        # Grayscale between 0 and 1
achsen.plot(x, np.sin(x - 3), color='#FFDD44')     # Hex code (RRGGBB from 00 to FF)
achsen.plot(x, np.sin(x - 4), color=(1.0,0.2,0.3)) # RGB tuple, values 0 to 1
achsen.plot(x, np.sin(x - 5), color='chartreuse'); # all HTML color names supported 

Die Linienstile können mit linestyle=... in Lang- oder Kurzform angegeben werden, jeweils in Form von Zeichenketten:

  • solid oder -
  • dashed oder --
  • dashdot oder -.
  • dotted oder :
  • beispielsweise linestyle='dashdot' oder linestyle='-.'. Linienfarbe und Linienstil können auch zusammen angegegen werden, wenn für die Farbe ebenfalls die Kurzform (rgbcmyk, (Red/Green/Blue, Cyan/Magenta/Yellow/blacK) genutzt wird:
  • '-g' # solid und green
  • '--y' # dashed und yellow
  • '-.k' # dashdot und black
  • ':b' # dotted und blue
  • Achsenbereich

    Ohne Angabe eines Bereiches übernimmt mathlotlib in Abhängigkeit der x-Werte die sinnvolle Einteilung der Achsen. Mit plt.xlim() und plt.ylim() können die BEreiche individuell festgelegt werden:

    # Hinweis
    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(0, 4*np.pi, 1000)
    plt.plot(x, np.sin(x))
    plt.xlim(-1, 11)
    plt.ylim(-1.5, 1.5)

    Etwas verwirrend ist die Tatsache, dass sich gleiches auch über die Funktion plt.axis([...]) erreichen lässt.

    # Hinweis
    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(0, 4*np.pi, 1000)
    plt.plot(x, np.sin(x))
    plt.axis([-1, 11, -1.5, 1.5]);

    Mit plt.axis('tight') kann eine Achseneinteilung gewählt werden, die der Bounding Box entspricht, also den kleinst-möglichen Bereich auswählt. Mit plt.axis('equal') kann man eine proportionale Einteilung erreichen. Eine Längeneinheit auf der x-Achse entspricht dann bei einer trigonometrischen Funktion ca. 57°=180°/π.

    Beschriftungen (Label)

    Für die Beschriftung der Achsen und einem allgemeinen Titel gibt es eigene Funktionen, wohingegen eine Legende über die Optionen mit label=... definiert wird:

    # Hinweis
    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(0, 4*np.pi, 1000)
    plt.grid()
    plt.title("Eine Sinuskurve $y=\sin(x)$")
    plt.xlabel("x in rad");
    plt.ylabel("$2\sin(x) / 2\cos(x)$")
    plt.plot(x, 2*np.sin(x), '--r', label='$2\sin(x)$')
    plt.plot(x, 2*np.cos(x), ':b',  label='$2\cos(x)$')
    plt.axis('equal')
    plt.legend();

    Anstelle der verschiedenen Funktionen, die hier Matlab-like sind, kann auch mit der Methode ax.set(...) gearbeitet werden.

    # Hinweis
    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(0, 4*np.pi, 1000)
    plt.grid()
    ax = plt.axes(2)
    ax1.plot(x, np.sin(x))
    ax1.set(xlim=(0, 10), ylim=(-2, 2), xlabel='x', ylabel='sin(x)', title='A Simple Plot');
    ax2.plot(x, np.cos(x))
    ax1.set(xlim=(0, 10), ylim=(-2, 2), xlabel='x', ylabel='cos(x)');

    Weitere Möglichkeiten für Legenden gibt es im Data Science Handbook.

    Punktdiagramme (Scatter plots)

    Die Daten werden hierbei als einzelne Koordinatenpunkte aufgefasst, die im Gegensatz zum Liniendiagramm nicht verbunden werden. Die Punkte können mit einem Symbol, im einfachsten Fall mit einem kleinen ausgefüllten schwarzen Kreis markiert werden.

    # Hinweis
    import matplotlib.pyplot as plt
    import numpy as np
    plt.style.use('seaborn-whitegrid')
    
    fig, axs = plt.subplots(2, figsize=(10, 10))
    x = np.linspace(0, 10, 30)
    y = np.sin(x)
    
    axs[0].plot(x, y, 'o', color='black')
    axs[0].plot(x, y, '--', color='red')
    
    ng = np.random.RandomState(0)
    phase = 0 
    for marker in ['o', '.', ',', 'x', '+', 'v', '^', '<', '>', 's', 'd']:
        axs[1].plot(x, np.sin(x+phase), marker, label="marker='{0}'".format(marker))
        phase += 0.2
    plt.legend(numpoints=2, frameon=True)
    plt.xlim(0, 4*np.pi);
    plt.show()

    Sämtliche Randbedingungen für die Punkte können indivisuelle eingestellt werden, beispielsweise:

    # Hinweis
    import matplotlib.pyplot as plt
    import numpy as np
    plt.style.use('seaborn-whitegrid')
    
    x = np.linspace(0, 10, 30)
    y = np.sin(x)
    plt.plot(x, y, '-p', color='gray', markersize=15, linewidth=4, markerfacecolor='red', markeredgecolor='gray', markeredgewidth=2)
    plt.ylim(-1.2, 1.2);
    plt.show()

    Es existiert auch eine Funktion plt.scatter(), welche eine einfachere Handhabung ermöglicht, jedoch bei sehr großen Datenmengen nicht so effizient arbeitet.

    # Hinweis
    import matplotlib.pyplot as plt
    import numpy as np
    plt.style.use('seaborn-whitegrid')
    rng = np.random.RandomState(0)
    x = rng.randn(100)
    y = rng.randn(100)
    colors = rng.rand(100)
    sizes = 1000 * rng.rand(100)
    
    plt.scatter(x, y, c=colors, s=sizes, alpha=0.3, cmap='viridis')
    plt.colorbar();  # show color scale
    plt.show()

    Alle weiteren Optionen kann man der Dokumentation von pyplot entnehmen: https://matplotlib.org/api/pyplot_api.html

    Weitere Möglichkeiten

  • Visualizing Errors
  • Density and Contour Plots
  • Histograms, Binnings, and Density
  • Customizing Plot Legends
  • Customizing Colorbars
  • Multiple Subplots
  • Text and Annotation
  • Customizing Ticks
  • Customizing Matplotlib: Configurations and Stylesheets
  • Three-Dimensional Plotting in Matplotlib
  • Geographic Data with Basemap
  • Visualization with Seaborn
  • Further Resources
  • Background Code

    # Hinweis
    from PIL import Image
    from apscheduler.schedulers.background import BackgroundScheduler
    
    w, h, zoom = 1920, 1080, 1
    # creating the new image in RGB mode
    bitmap = Image.new("RGB", (w, h), "white")
    pix = bitmap.load()
    
    cX, cY = -0.7, 0.27015
    moveX, moveY = 0.0, 0.0
    maxIter = 255
    
    def dots():
        print(".",end="")
    
    #Kontrolle = BackgroundScheduler()
    #Kontrolle.add_job(dots, 'interval', seconds=1)
    #Kontrolle.start()
    
    for x in range(w):
         for y in range(h):
             zx = 1.5 * (x - w / 2) / (0.5 * zoom * w) + moveX
             zy = 1.0 * (y - h / 2) / (0.5 * zoom * h) + moveY
             i = maxIter
             while zx * zx + zy * zy < 4 and i > 1:
                 tmp = zx * zx - zy * zy + cX
                 zy, zx = 2.0 * zx * zy + cY, tmp
                 i -= 1
             # convert byte to RGB (3 bytes) RedGreenBlue
             pix[x, y] = (i << 21) + (i << 10) + i * 8
    #Kontrolle.shutdown()
    bitmap.show()

    Nächste Einheit: 08 Anwendungen