# 4.NumPy_MatPlotLib_Lösungen slides

# Lösungen Numpy & MatPlotLib¶

## Aufgabe¶

1 Punkt

Erstellen Sie ein NumPy Array, welches 6 Nullen reserviert und speichern Sie das Array in der Variablen `only_zeros`.

In [3]:

    only_zeros = np.zeros(6)
    only_zeros

Out[3]:

    array([0., 0., 0., 0., 0., 0.])

## Aufgabe¶

1 Punkt

Erstellen Sie ein NumPy Array mit 11 Elementen mittels `linspace`. Dabei soll der Startwert = -4 und der Endwert = 17 sein. Speichern Sie das Ergbniss in der Variablen `x_scale`.

In [4]:

    x_scale = np.linspace(-4, 17, num=11)
    x_scale

Out[4]:

    array([-4. , -1.9,  0.2,  2.3,  4.4,  6.5,  8.6, 10.7, 12.8, 14.9, 17. ])

## Aufgabe - Erster eigener Plot Square Root¶

Analog zu voheriger Erklärung plotten Sie im folgenden die Funktion Square Root, Mathematisch definiert als $f(x) = \sqrt x; \quad x \geq 0$.

Gehen Sie dabei wie folgt vor:

1. Definieren Sie einen geeigneten Linespace für die Zahlenraum 0...100. (Tipp: Achten Sie auf die Definition! Die Wurzel ist nur für positive Zahlen definiert.)
2. Berechnen Sie mittels der Funktion np.sqrt die Werte für die Wurzel.
3. Plotten Sie das Ergebnis

In [5]:

    xs = np.linspace(0, 100, num=200)
    ys = np.sqrt(xs)
    plt.plot(xs, ys)
    plt.show()

## Aufgabe - Multiplot¶

8 Punkte

In der nächsten Aufgabe wollen wir gleich zwei Funktionen plotten. $f(x) = \sqrt x; x \geq 0$ und $g(x) = x^2$.

Gehen Sie dabei wie folgt vor:

1. Definieren Sie einen geeigneten Linespace für die Zahlenraum 0...3. (Tipp: Achten Sie auf die Definition! Die Wurzel ist nur für positive Zahlen definiert.)
2. Berechnen Sie mittels der Funktion np.sqrt die Werte für die Wurzel.
3. Berechnen Sie mittels der Funktion np.square die Werte für die Quadratzahlen
4. Geben Sie den beiden Plots die Farben Grün & Rot. Nutzen Sie gerne die Color Shorthands aus der Dokumentation.
5. Plotten Sie die Square Funktion mit dem Linestyle `dashdot`, wie der Dokumentation zu entnehmen Linestyles
6. Geben Sie den beiden Plots angemessene Labels.
7. Fügen Sie die Legende hinzu.
8. Plotten Sie das Ergebnis.

In [6]:

    xt = np.linspace(0, 3, num=200)
    sqrt = np.sqrt(xt)
    square = np.square(xt)

    plt.plot(xt, sqrt, color='r', label="Square Root")
    plt.plot(xt, square, color='g', label="Square Function", linestyle="dashdot")
    plt.legend()
    plt.show()

## Aufgabe¶

6 Punkte

Schreibe einen Linear Congruent Generator mit dem funktionsnamen `lcg`.

- Nutze die oben gegebene Definition
- Prüfe auch, das Werte nicht verwendet werden dürfen (Bsp. $n \geq 0$)
- `lcg` muss ein unendlicher Generator sein

# Pseudo Randomness¶

Zufallszahlen in Computern werden über Formeln berechnet. Einer dieser Generatoren ist der Linear Congruent Generator (LCG), dessen mathematische Grundlage leicht verdaulich ist.

$$ X_{n+1} = (aX_n + c) \;mod\; m; \quad n \geq 0 $$

Wenn $ c = 0 $ dann nennt man den Generator auch Multiplicative Congruent Generator (MCG).

Die Werte haben folgenden Nutzen in der Funktion:

- $X_n$ ist der Startwert oder seed
- $X_{n+1}$ ist der Folgewert der im nächsten Schritt für $X_n$ eingesetzt wird
- $a$ ist der Vorfaktor vom Startwert. Dieser wird skaliert, deshalb wird er Skalar gennant
- $c$ ist das hinzuaddierte Offset
- $m$ ist der Restklassenring oder auch Modulus genannt

In [7]:

    def lcg(seed: int, scalar: int, modulus: int, offset: int) -> int:
        '''
        Linear Congruential Generators

        X(n+1) = (a X(n) + c) mod m; n >= 0

        m > 0;
        0 <= a < m;
        c > 0; a > 0

        '''
        assert modulus > 0, "Modulus must be greater than 0"
        assert 0 <= scalar and scalar < modulus, "Scalar must be in range 0 <= a < m"

        while seed > 1:
            seed = (scalar*seed+offset) % modulus
            assert seed >= 0
            yield seed

In [11]:

    # Cocktailshaker Numbers
    rng = lcg(
            3935559000370003845,
            3203021881815356449,
            2**64-1, 11742185885288659963
        )

    for i in range(1,6):
        print(f"{i}.", next(rng))

    1. 3089810780120156248
    2. 8356396685252565260
    3. 1921117399837525548
    4. 14806858147081821235
    5. 2557599628047639428

## Aufgabe¶

6 Punkte

Plote die Zufallszahlen eines Permuted Congruent Generators mittels NumPy & MatPlotLib.

- Gegeben ist der Anfangszustand des Generators.
- Nutze die Dokumentation und rufe den `default_rng` aus dem `numpy.random` Modul, 20 mal auf speichere die Werte in der variablen `pcgs`. (Tipp: Nutze ein NumPy Array)
- Sortiere im nächsten Schritt die in `pcgs` gespeicherten Werte und speichere diese in `pcgs_sorted`
- Plotte sinnvoll beide Array. Gestalte den Plot angemessen.

In [12]:

    # Given
    np.random.seed(42) # Setting a fixed start Value for the Generator
    pcgs: np.array = None
    pcgs_sorted: np.array = None

In [13]:

    gen = np.random.default_rng()
    pcgs = np.array([gen.random() for _ in range(20)])
    pcgs_sorted = np.sort(pcgs)

    # Plot
    plt.plot(np.arange(len(pcgs_sorted)), pcgs, color='r', label='PCGs')
    plt.plot(np.arange(len(pcgs_sorted)), pcgs_sorted, color='g', label='Sortierte PCGs')
    plt.title("PCG Random Numbers")
    plt.legend()
    plt.show()

### Aufgabe¶

5 Punkte

Ihnen ist ein Datenset `sec_school` einer Hauptschule gegeben, welches die Klassenstufen von 5 bis 9 auf die Anzahl ihrer Schüler im Jahrgang mappt.

Definieren Sie einen Barplot. Gehen Sie dabei wie folgt vor:

1. Definieren Sie ein geeignetes Farbschema zur Darstellung der Daten.
2. Extrahieren Sie die Schlüssel und Werte aus dem Datenset und übergeben Sie diese zusammen mit den Farbwerten an die Funktion `plt.bar`.
3. Setzen Sie geeignete Werte für die X & Y-Achse.
4. Setzen Sie einen geeigneten Titel für den Plot.
5. Plotten Sie den Werte

In [14]:

    # Given
    sec_school = {
        '5. Klasse': 29,
        '6. Klasse': 35,
        '7. Klasse': 25,
        '8. Klasse': 28,
        '9. Klasse': 31
    }

In [15]:

    colors = ["red", "blue", "green", "yellow", "pink"]
    plt.bar(sec_school.keys(), sec_school.values(), color=colors)
    plt.xlabel("Klassenstufe")
    plt.ylabel("Anzahl Kinder")
    plt.title("Verteilung Kinder einer Hauptschule pro Klassenstufe")
    plt.show()

## Aufgabe¶

5 Punkte

Ihnen ist ein Datenset `sec_school` einer Hauptschule gegeben, welches die Klassenstufen von 5 bis 9 auf die Anzahl ihrer Schüler im Jahrgang mappt.

Definieren Sie einen Pieplot. Gehen Sie dabei wie folgt vor:

1. Definieren Sie ein geeignetes Farbschema zur Darstellung der Daten.
2. Extrahieren Sie die Schlüssel und Werte aus dem Datenset und übergeben Sie diese zusammen mit den Farbwerten an die Funktion `plt.pie`. (Nutzen Sie zum Anzeigen der Prozentwerte autopct='%1.1f%%')
3. Lassen Sie die 6. Klasse 25% und die 9. Klasse 40% explodieren.
4. Setzen Sie einen geeigneten Titel für den Plot.
5. Plotten Sie den Werte.

In [16]:

    # Given
    sec_school = {
        '5. Klasse': 29,
        '6. Klasse': 35,
        '7. Klasse': 25,
        '8. Klasse': 28,
        '9. Klasse': 31
    }

In [17]:

    plt.pie(
        sec_school.values(),
        labels=sec_school.keys(),
        autopct='%1.1f%%',
        explode=[0, 0.25, 0, 0, 0.4]
    )

    plt.title("Klassenverteilung einer Grundschule")

    plt.show()

# Extra: The Meme¶

In [18]:

    data = {
        "Sky": 0.77,
        "Sunny side of pyramid": 0.17,
        "Shady side of pyramid": 0.05
    }
    colors = ["#0095d9", "#f5e837", "#c4b633"]
    plt.pie(data.values(), startangle=-50, colors=colors)
    plt.legend(data.keys(), bbox_to_anchor=(1, 0, 0.5, 0.6))
    plt.savefig("meme.png", bbox_inches="tight", transparent=True)