diff --git a/02-python-vertiefung/folien-code/data.csv b/02-python-vertiefung/folien-code/data.csv
new file mode 100644
index 0000000000000000000000000000000000000000..42a883a6e1b9d953b6231a8e22ab105e91068c9f
--- /dev/null
+++ b/02-python-vertiefung/folien-code/data.csv
@@ -0,0 +1,6 @@
+x1,x2,x3,y
+25,1,20,0
+5,16,2,1
+13,21,13,1
+17,9,11,0
+21,17,13,1
\ No newline at end of file
diff --git a/02-python-vertiefung/folien-code/folien-code.ipynb b/02-python-vertiefung/folien-code/folien-code.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..8414244d1806a74f80f05f25c2614fa5a89b11d8
--- /dev/null
+++ b/02-python-vertiefung/folien-code/folien-code.ipynb
@@ -0,0 +1,558 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    " # Code zu Folien\n",
+    "\n",
+    "\n",
+    "\n",
+    " Dieses Skript bzw. Jupyter-Notebook enthält den Code, der auch auf den Folien \"Python Vertiefung\" enthalten ist. Zum Vorbereiten, Mitmachen oder Nacharbeiten."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "a = [1, 3, 5]\n",
+    "b = a              # b ist eine weitere Referenz\n",
+    "print(a, b)\n",
+    "\n",
+    "b[1] = 10          # ändere Objekt, das b referenziert\n",
+    "print(a, b)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "a = [1, 3, 5]\n",
+    "b = a                  # b ist eine weitere Referenz\n",
+    "c = [1, 3, 5]          # zweites Objekt\n",
+    "print(a == b, a is b)  # a und b sind dasselbe Objekt\n",
+    "print(a == c, a is c)  # a und c sind gleich, aber verschiedene Objekte\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "a = [1, [3], 5]   # Objekt in Objekt\n",
+    "b = a.copy()      # b ist eine flache Kopie\n",
+    "print(a, b)\n",
+    "\n",
+    "b[0] = 2         # ändere Objekt auf das b referenziert\n",
+    "b[1].append(4)   # ändere Objekt auf das das Objekt referenziert auf das b referenziert\n",
+    "print(a, b)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "t = (1, 2, 3)\n",
+    "a, b, c = t   # auf der linken Seite darf ein Tupel oder eine Liste von Variablen stehen\n",
+    "\n",
+    "def fun(x, y, z):\n",
+    "    print(x, y, z)\n",
+    "\n",
+    "t = (1, 2, 3)              # Reihenfolge wird beibehalten\n",
+    "fun(*t)                    # ergibt: 1 2 3\n",
+    "\n",
+    "d = {'z':1, 'y':2, 'x':3}  # Reihenfolge ist hier unwichtig, aber Namen müssen übereinstimmen\n",
+    "fun(**d)                   # ergibt: 3 2 1\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def fun(*args):\n",
+    "    print(len(args), 'Argumente:', args)\n",
+    "\n",
+    "fun(1, 2, 3)            # ergibt: 3 Argumente: (1, 2, 3)\n",
+    "fun('hello', 'python')  # ergibt: 2 Argumente: ('hello', 'python')\n",
+    "\n",
+    "def fun(**kwargs):\n",
+    "    print(len(kwargs), 'Argumente:', kwargs)\n",
+    "\n",
+    "fun(y=1, x=2, z=3)      # ergibt: 3 Argumente: {'y': 1, 'x': 2, 'z': 3}\n",
+    "\n",
+    "def fun(*args, **kwargs):\n",
+    "    print('args:', args, 'kwargs:', kwargs)\n",
+    "\n",
+    "fun(1, 2, x=3, y=4)     # ergibt args: (1, 2) kwargs: {'x': 3, 'y': 4}\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def f(a, b):\n",
+    "    return a(b)\n",
+    "\n",
+    "f(print, 'test')                   # normale print-Funktion übergeben\n",
+    "\n",
+    "def arg_fun(s):\n",
+    "    return s * 2\n",
+    "\n",
+    "print(f(arg_fun, 'test'))\n",
+    "\n",
+    "arg_fun = lambda s: s * 2          # analog zu def arg_fun(s): return s * 2\n",
+    "print(f(arg_fun, 'test'))\n",
+    "\n",
+    "print(f(lambda s: s * 2, 'test'))  # analog zu def arg_fun(s): return s * 2\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def multiplier(a):\n",
+    "    def multiply(b):\n",
+    "        return a * b\n",
+    "    return multiply\n",
+    "\n",
+    "five_times = multiplier(5)\n",
+    "ten_times = multiplier(10)\n",
+    "print(five_times(6))\n",
+    "print(ten_times(1))\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def make_stars(fun):\n",
+    "    def wrapped_in_stars():\n",
+    "        print('*' * 30)\n",
+    "        fun()  # call original function\n",
+    "        print('*' * 30)\n",
+    "    return wrapped_in_stars\n",
+    "\n",
+    "@make_stars\n",
+    "def hello_stars():\n",
+    "    print('Hello, stars! :-)')\n",
+    "\n",
+    "# starred = make_stars(hello_stars)\n",
+    "# starred()\n",
+    "\n",
+    "# hello_stars = make_stars(hello_stars)\n",
+    "hello_stars()\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import numpy             # numpy steht über numpy zur Verfügung\n",
+    "print(numpy.pi)\n",
+    "\n",
+    "import numpy as np       # numpy steht über np zur Verfügung (üblich)\n",
+    "print(np.pi)\n",
+    "\n",
+    "from numpy import pi     # nur numpy.pi steht über pi zur Verfügung\n",
+    "print(pi)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# check current working directory – must be in the same directory as mymodule.py\n",
+    "import os\n",
+    "assert 'mymodule.py' in os.listdir(), f'mymodule.py is not in the current working directory of the python interpreter. You are here: {os.getcwd()}'\n",
+    "\n",
+    "# try code from slide\n",
+    "import mymodule  # gibt nur beim ersten Import etwas aus\n",
+    "\n",
+    "mymodule.say_hello('you')\n",
+    "\n",
+    "print(mymodule.__file__)\n",
+    "\n",
+    "help(mymodule)  # Hilfe anzeigen\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "\n",
+    "# gibt nur beim ersten Import etwas aus\n",
+    "import mypackage\n",
+    "from mypackage.mymod import say_hello\n",
+    "\n",
+    "mypackage.say_hello('you')\n",
+    "say_hello('you')\n",
+    "\n",
+    "# hier muss das Modul \"more\" explizit importiert werden, da die Init-Datei leer ist\n",
+    "import mypackage.subpackage.more\n",
+    "mypackage.subpackage.more.say_bye()\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "f = open('data.csv')\n",
+    "header = f.readline()\n",
+    "print(header)\n",
+    "\n",
+    "# for line in f.readlines():  # iteriert über alle Zeilen\n",
+    "for line in f:                # oder kürzer: for line in f: iteriert auch über alle Zeilen\n",
+    "    print(line.strip())       # strip entfernt \\n um Leerzeilen zu vermeiden\n",
+    "\n",
+    "f.close()\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "f = open('test.md', mode='w')\n",
+    "f.write('# Schreibtest\\n\\n')\n",
+    "print('Kleiner Test', file=f)\n",
+    "f.writelines(['\\n', '- bli\\n', '- bla\\n'])\n",
+    "f.write('\\n'.join(['', '- blupp', '- blupp\\n']))\n",
+    "f.close()\n",
+    "\n",
+    "# Ausgabe der Datei\n",
+    "f = open('test.md')\n",
+    "print(f.read())\n",
+    "f.close()\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "\n",
+    "f = open('data.csv')\n",
+    "print(f.closed)\n",
+    "f.close()\n",
+    "print(f.closed)\n",
+    "\n",
+    "with open('data.csv') as f:\n",
+    "    # innerhalb dieses Blocks ist die Datei offen\n",
+    "    header = f.readline()\n",
+    "    print(f.closed)         # ergibt: False\n",
+    "\n",
+    "# außerhalb des Blocks ist die Datei geschlossen\n",
+    "print(f.closed)             # ergibt: True\n",
+    "print(header)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "p = 'summe.ipynb'                            # relativer Pfad zu einer Datei\n",
+    "dirname, filename = os.path.split(p)         # splitte Pfad in Verzeichnis und Datei\n",
+    "base, ext = os.path.splitext(filename)       # splitte Datei in Basis und Erweiterung\n",
+    "print(dirname, filename, base, ext, sep=', ')\n",
+    "\n",
+    "absdir = os.path.abspath(dirname)            # wandle dirname zu absoluten Pfad um\n",
+    "absfile = os.path.join(absdir, base + '.py') # fügt mit Pfadtrenner zusammen\n",
+    "print(absfile)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import pathlib\n",
+    "\n",
+    "p = pathlib.Path('summe.ipynb')        # relativer Pfad zu einer Datei\n",
+    "abs_p = p.absolute()                   # wandle p zu absoluten Pfad um (hier: irrelevant)\n",
+    "abs_py = abs_p.with_suffix('.py')      # Dateinamenserweiterung tauschen\n",
+    "print(abs_py)\n",
+    "\n",
+    "framework_dir = abs_p.parent.parent    # gehe zweimal \"hoch\"\n",
+    "print(framework_dir)                   # (ginge auch relativ: PosixPath('..'))\n",
+    "\n",
+    "prod_ex = framework_dir / 'funktionen' / 'prod.py'  # füge mit Pfadtrenner an\n",
+    "print(prod_ex)\n",
+    "\n",
+    "file_content = prod_ex.read_text()                          # Datei einlesen\n",
+    "prod_ex.with_name('prod_copy.py').write_text(file_content)  # Datei schreiben\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from glob import glob\n",
+    "files = glob('~/data-science-notebooks/*grundlagen/*-sol.ipynb')\n",
+    "print(files)\n",
+    "\n",
+    "files = glob('~/data-science-notebooks/**/[g-h]*-sol.ipynb', recursive=True)\n",
+    "print(files)\n",
+    "\n",
+    "paths = pathlib.Path('..').glob('**/[a-g]*.ipynb')\n",
+    "print(list(paths))\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def nthroot(x: float, n: float = 2) -> float:\n",
+    "    \"\"\"nth root of a number\n",
+    "\n",
+    "    Parameters\n",
+    "    ----------\n",
+    "    x : float or int\n",
+    "        Number to take the root from.\n",
+    "    n : float or int, optional\n",
+    "        Root parameter (the default is 2).\n",
+    "\n",
+    "    Returns\n",
+    "    -------\n",
+    "    float\n",
+    "        The nth root.\n",
+    "    \"\"\"\n",
+    "\n",
+    "    return x ** (1/n)\n",
+    "\n",
+    "help(nthroot)\n",
+    "\n",
+    "print(nthroot(3, 3))\n",
+    "print(nthroot('asd', 3))  # um hier den Fehler sehen zu können, sollte mypy als Paket und VS Code Erweiterung installiert sein\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from pathlib import Path\n",
+    "\n",
+    "def tabs_to_spaces(filename):\n",
+    "    if '*' in filename:\n",
+    "        raise InvalidFileName(f'Filenames with * are not allowed: {filename}')  # message if not caught\n",
+    "        # raise ValueError(f'Filenames with * are not allowed: {filename}')       # message if not caught\n",
+    "\n",
+    "    p = Path(filename)\n",
+    "    file_contents = p.read_text().replace('\\t', '    ')\n",
+    "    p.write_text(file_contents)\n",
+    "\n",
+    "class InvalidFileName(Exception):\n",
+    "    pass\n",
+    "\n",
+    "filenames = ['data.csv', 'does-not-exist', '*.csv']\n",
+    "for filename in filenames:\n",
+    "    try:\n",
+    "\n",
+    "        tabs_to_spaces(filename)\n",
+    "    except FileNotFoundError as e:\n",
+    "        print(f'File {filename} not found, so also not converted to spaces.')\n",
+    "    # except ValueError as e:\n",
+    "    except InvalidFileName as e:\n",
+    "        print(f'Use proper filenames, not glob syntax. Resolve {filename} before using glob.glob.')\n",
+    "    except PermissionError as e:  # e enthält die Fehlernachricht als str(e)\n",
+    "        print(e, 'Could not convert to spaces.', sep='. ')\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def fun():\n",
+    "    with open('does-not-exist') as f:\n",
+    "        f.read()\n",
+    "\n",
+    "fun()  # FileNotFoundError\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class MyComplex:\n",
+    "    def __init__(self, re=0, im=0):  # Konstruktor mit zwei \"echten\" Argumenten\n",
+    "        self.re = re\n",
+    "        self.im = im\n",
+    "\n",
+    "    def conjugate(self):             # Methode ohne \"echte\" Argumente\n",
+    "        return MyComplex(self.re, -self.im)\n",
+    "\n",
+    "    def __repr__(self):  # wird über repr(z) (und ggf. über str(z)) aufgerufen\n",
+    "        return f'MyComplex({self.re}, {self.im})'\n",
+    "\n",
+    "    def __str__(self):   # wird über str(z) aufgerufen\n",
+    "        return f'({self.re}{self.im:+}j)'\n",
+    "\n",
+    "z1 = MyComplex(3, 4)\n",
+    "z2 = z1.conjugate()\n",
+    "print(f'z1: ({z1.re}, {z1.im})')\n",
+    "print(f'z2: ({z2.re}, {z2.im})')\n",
+    "print(repr(z1))\n",
+    "print(z1)        # ruft intern str(z) auf, das als Fallback repr(z) aufrufen würde\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class A:\n",
+    "    def __bar(self):\n",
+    "        print('...not really private...')\n",
+    "a = A()\n",
+    "# a.__bar()    # So geht es zwar nicht...\n",
+    "a._A__bar()  # aber so\n",
+    "\n",
+    "class B:\n",
+    "    def _foo(self):\n",
+    "        print('foo!')\n",
+    "\n",
+    "b = B()\n",
+    "b._foo()\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class MyPositiveNumber:\n",
+    "  def __init__(self, r=0):\n",
+    "    self.r = r\n",
+    "\n",
+    "num = MyPositiveNumber(3)\n",
+    "num.r = -8          # schreiben\n",
+    "print(num.r)        # lesen, ergibt -8\n",
+    "\n",
+    "class MyPositiveNumber:\n",
+    "  def __init__(self, r=0):\n",
+    "    self.r = r  # benutzt schon setter unten\n",
+    "\n",
+    "  @property     # getter\n",
+    "  def r(self):\n",
+    "    return self._r\n",
+    "\n",
+    "  @r.setter     # setter\n",
+    "  def r(self, val):\n",
+    "    self._r = val if val > 0 else 0\n",
+    "\n",
+    "num = MyPositiveNumber(3)\n",
+    "num.r = -8      # ruft setter auf\n",
+    "print(num.r)    # ruft getter auf, ergibt: 0\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class MyPositiveComplex(MyPositiveNumber): # erbt von MyPositiveNumber\n",
+    "    def __init__(self, r=0, i=0):\n",
+    "        super().__init__(r)                # rufe Konstruktor von MyPositiveNumber auf\n",
+    "        self.i = i                         # benutzt schon setter unten\n",
+    "\n",
+    "    @property                              # getter\n",
+    "    def i(self):\n",
+    "        return self._i\n",
+    "\n",
+    "    @i.setter                              # setter\n",
+    "    def i(self, val):\n",
+    "        self._i = val if val > 0 else 0\n",
+    "\n",
+    "c = MyPositiveComplex(-8, 1)\n",
+    "c.i = -5                                   # ruft setter auf\n",
+    "print(f'{c.r} + {c.i}j')                   # ruft getter auf, ergibt: 0 + 0j\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class Text:\n",
+    "    def __init__(self, text):\n",
+    "        self.text = text\n",
+    "\n",
+    "    @classmethod\n",
+    "    def from_file(cls, path):\n",
+    "        with open(path) as f:\n",
+    "            return cls(f.read())\n",
+    "\n",
+    "class GradedText(Text):\n",
+    "    def __init__(self, text, grade=None):\n",
+    "        super().__init__(text)\n",
+    "        self.grade = grade\n",
+    "\n",
+    "file = 'data.csv'\n",
+    "t =  Text.from_file(file)\n",
+    "print(t.text)\n",
+    "print(type(t))\n",
+    "\n",
+    "gt = GradedText.from_file(file)\n",
+    "print(gt.text, gt.grade)\n",
+    "print(type(gt))\n"
+   ]
+  }
+ ],
+ "metadata": {
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": 3
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/02-python-vertiefung/folien-code/folien-code.py b/02-python-vertiefung/folien-code/folien-code.py
new file mode 100644
index 0000000000000000000000000000000000000000..9893814371d497a3c00ac3f58311fba8e7c2037c
--- /dev/null
+++ b/02-python-vertiefung/folien-code/folien-code.py
@@ -0,0 +1,381 @@
+# %% [markdown]
+# # Code zu Folien
+#
+# Dieses Skript bzw. Jupyter-Notebook enthält den Code, der auch auf den Folien "Python Vertiefung" enthalten ist. Zum Vorbereiten, Mitmachen oder Nacharbeiten.
+
+# %% Referenzen
+a = [1, 3, 5]
+b = a              # b ist eine weitere Referenz
+print(a, b)
+
+b[1] = 10          # ändere Objekt, das b referenziert
+print(a, b)
+
+# %% Gleichheit und Identität
+a = [1, 3, 5]
+b = a                  # b ist eine weitere Referenz
+c = [1, 3, 5]          # zweites Objekt
+print(a == b, a is b)  # a und b sind dasselbe Objekt
+print(a == c, a is c)  # a und c sind gleich, aber verschiedene Objekte
+
+# %% Flache Kopie
+a = [1, [3], 5]   # Objekt in Objekt
+b = a.copy()      # b ist eine flache Kopie
+print(a, b)
+
+b[0] = 2         # ändere Objekt auf das b referenziert
+b[1].append(4)   # ändere Objekt auf das das Objekt referenziert auf das b referenziert
+print(a, b)
+
+# %% Übergabe an Funktionsargumente
+t = (1, 2, 3)
+a, b, c = t   # auf der linken Seite darf ein Tupel oder eine Liste von Variablen stehen
+
+def fun(x, y, z):
+    print(x, y, z)
+
+t = (1, 2, 3)              # Reihenfolge wird beibehalten
+fun(*t)                    # ergibt: 1 2 3
+
+d = {'z':1, 'y':2, 'x':3}  # Reihenfolge ist hier unwichtig, aber Namen müssen übereinstimmen
+fun(**d)                   # ergibt: 3 2 1
+
+# %% Beliebige Anzahl Argumente
+def fun(*args):
+    print(len(args), 'Argumente:', args)
+
+fun(1, 2, 3)            # ergibt: 3 Argumente: (1, 2, 3)
+fun('hello', 'python')  # ergibt: 2 Argumente: ('hello', 'python')
+
+def fun(**kwargs):
+    print(len(kwargs), 'Argumente:', kwargs)
+
+fun(y=1, x=2, z=3)      # ergibt: 3 Argumente: {'y': 1, 'x': 2, 'z': 3}
+
+def fun(*args, **kwargs):
+    print('args:', args, 'kwargs:', kwargs)
+
+fun(1, 2, x=3, y=4)     # ergibt args: (1, 2) kwargs: {'x': 3, 'y': 4}
+
+# %% Funktionen als Objekte
+def f(a, b):
+    return a(b)
+
+f(print, 'test')                   # normale print-Funktion übergeben
+
+def arg_fun(s):
+    return s * 2
+
+print(f(arg_fun, 'test'))
+
+arg_fun = lambda s: s * 2          # analog zu def arg_fun(s): return s * 2
+print(f(arg_fun, 'test'))
+
+print(f(lambda s: s * 2, 'test'))  # analog zu def arg_fun(s): return s * 2
+
+# %% Funktionen als Rückgabewerte / Closure
+def multiplier(a):
+    def multiply(b):
+        return a * b
+    return multiply
+
+five_times = multiplier(5)
+ten_times = multiplier(10)
+print(five_times(6))
+print(ten_times(1))
+
+# %% Decorators
+def make_stars(fun):
+    def wrapped_in_stars():
+        print('*' * 30)
+        fun()  # call original function
+        print('*' * 30)
+    return wrapped_in_stars
+
+@make_stars
+def hello_stars():
+    print('Hello, stars! :-)')
+
+# starred = make_stars(hello_stars)
+# starred()
+
+# hello_stars = make_stars(hello_stars)
+hello_stars()
+
+# %% Module importieren
+import numpy             # numpy steht über numpy zur Verfügung
+print(numpy.pi)
+
+import numpy as np       # numpy steht über np zur Verfügung (üblich)
+print(np.pi)
+
+from numpy import pi     # nur numpy.pi steht über pi zur Verfügung
+print(pi)
+
+# %% Eigene Module
+# check current working directory – must be in the same directory as mymodule.py
+import os
+assert 'mymodule.py' in os.listdir(), f'mymodule.py is not in the current working directory of the python interpreter. You are here: {os.getcwd()}'
+
+# try code from slide
+import mymodule  # gibt nur beim ersten Import etwas aus
+
+mymodule.say_hello('you')
+
+print(mymodule.__file__)
+
+help(mymodule)  # Hilfe anzeigen
+
+# %% Eigene Pakete
+
+# gibt nur beim ersten Import etwas aus
+import mypackage
+from mypackage.mymod import say_hello
+
+mypackage.say_hello('you')
+say_hello('you')
+
+# hier muss das Modul "more" explizit importiert werden, da die Init-Datei leer ist
+import mypackage.subpackage.more
+mypackage.subpackage.more.say_bye()
+
+# %%  Dateien lesen
+f = open('data.csv')
+header = f.readline()
+print(header)
+
+# for line in f.readlines():  # iteriert über alle Zeilen
+for line in f:                # oder kürzer: for line in f: iteriert auch über alle Zeilen
+    print(line.strip())       # strip entfernt \n um Leerzeilen zu vermeiden
+
+f.close()
+
+# %% Dateien schreiben
+f = open('test.md', mode='w')
+f.write('# Schreibtest\n\n')
+print('Kleiner Test', file=f)
+f.writelines(['\n', '- bli\n', '- bla\n'])
+f.write('\n'.join(['', '- blupp', '- blupp\n']))
+f.close()
+
+# Ausgabe der Datei
+f = open('test.md')
+print(f.read())
+f.close()
+
+# %% Dateien öffnen und schließen mit Kontext-Manager
+
+f = open('data.csv')
+print(f.closed)
+f.close()
+print(f.closed)
+
+with open('data.csv') as f:
+    # innerhalb dieses Blocks ist die Datei offen
+    header = f.readline()
+    print(f.closed)         # ergibt: False
+
+# außerhalb des Blocks ist die Datei geschlossen
+print(f.closed)             # ergibt: True
+print(header)
+
+# %% Pfade als Objekt: String
+p = 'summe.ipynb'                            # relativer Pfad zu einer Datei
+dirname, filename = os.path.split(p)         # splitte Pfad in Verzeichnis und Datei
+base, ext = os.path.splitext(filename)       # splitte Datei in Basis und Erweiterung
+print(dirname, filename, base, ext, sep=', ')
+
+absdir = os.path.abspath(dirname)            # wandle dirname zu absoluten Pfad um
+absfile = os.path.join(absdir, base + '.py') # fügt mit Pfadtrenner zusammen
+print(absfile)
+
+# %% Pfade als Objekt: pathlib
+import pathlib
+
+p = pathlib.Path('summe.ipynb')        # relativer Pfad zu einer Datei
+abs_p = p.absolute()                   # wandle p zu absoluten Pfad um (hier: irrelevant)
+abs_py = abs_p.with_suffix('.py')      # Dateinamenserweiterung tauschen
+print(abs_py)
+
+framework_dir = abs_p.parent.parent    # gehe zweimal "hoch"
+print(framework_dir)                   # (ginge auch relativ: PosixPath('..'))
+
+prod_ex = framework_dir / 'funktionen' / 'prod.py'  # füge mit Pfadtrenner an
+print(prod_ex)
+
+file_content = prod_ex.read_text()                          # Datei einlesen
+prod_ex.with_name('prod_copy.py').write_text(file_content)  # Datei schreiben
+
+# %% Dateinamen finden mittels glob-Syntax
+from glob import glob
+files = glob('~/data-science-notebooks/*grundlagen/*-sol.ipynb')
+print(files)
+
+files = glob('~/data-science-notebooks/**/[g-h]*-sol.ipynb', recursive=True)
+print(files)
+
+paths = pathlib.Path('..').glob('**/[a-g]*.ipynb')
+print(list(paths))
+
+# %% Docstrings und Type Hinting
+def nthroot(x: float, n: float = 2) -> float:
+    """nth root of a number
+
+    Parameters
+    ----------
+    x : float or int
+        Number to take the root from.
+    n : float or int, optional
+        Root parameter (the default is 2).
+
+    Returns
+    -------
+    float
+        The nth root.
+    """
+
+    return x ** (1/n)
+
+help(nthroot)
+
+print(nthroot(3, 3))
+print(nthroot('asd', 3))  # um hier den Fehler sehen zu können, sollte mypy als Paket und VS Code Erweiterung installiert sein
+
+# %% Fehler werfen und behandeln
+from pathlib import Path
+
+def tabs_to_spaces(filename):
+    if '*' in filename:
+        raise InvalidFileName(f'Filenames with * are not allowed: {filename}')  # message if not caught
+        # raise ValueError(f'Filenames with * are not allowed: {filename}')       # message if not caught
+
+    p = Path(filename)
+    file_contents = p.read_text().replace('\t', '    ')
+    p.write_text(file_contents)
+
+class InvalidFileName(Exception):
+    pass
+
+filenames = ['data.csv', 'does-not-exist', '*.csv']
+for filename in filenames:
+    try:
+
+        tabs_to_spaces(filename)
+    except FileNotFoundError as e:
+        print(f'File {filename} not found, so also not converted to spaces.')
+    # except ValueError as e:
+    except InvalidFileName as e:
+        print(f'Use proper filenames, not glob syntax. Resolve {filename} before using glob.glob.')
+    except PermissionError as e:  # e enthält die Fehlernachricht als str(e)
+        print(e, 'Could not convert to spaces.', sep='. ')
+
+# %% Traceback
+def fun():
+    with open('does-not-exist') as f:
+        f.read()
+
+fun()  # FileNotFoundError
+
+# %% MyComplex
+class MyComplex:
+    def __init__(self, re=0, im=0):  # Konstruktor mit zwei "echten" Argumenten
+        self.re = re
+        self.im = im
+
+    def conjugate(self):             # Methode ohne "echte" Argumente
+        return MyComplex(self.re, -self.im)
+
+    def __repr__(self):  # wird über repr(z) (und ggf. über str(z)) aufgerufen
+        return f'MyComplex({self.re}, {self.im})'
+
+    def __str__(self):   # wird über str(z) aufgerufen
+        return f'({self.re}{self.im:+}j)'
+
+z1 = MyComplex(3, 4)
+z2 = z1.conjugate()
+print(f'z1: ({z1.re}, {z1.im})')
+print(f'z2: ({z2.re}, {z2.im})')
+print(repr(z1))
+print(z1)        # ruft intern str(z) auf, das als Fallback repr(z) aufrufen würde
+
+# %% Kapselung
+class A:
+    def __bar(self):
+        print('...not really private...')
+a = A()
+# a.__bar()    # So geht es zwar nicht...
+a._A__bar()  # aber so
+
+class B:
+    def _foo(self):
+        print('foo!')
+
+b = B()
+b._foo()
+
+# %% Getter und Setter mit Decorator property
+class MyPositiveNumber:
+  def __init__(self, r=0):
+    self.r = r
+
+num = MyPositiveNumber(3)
+num.r = -8          # schreiben
+print(num.r)        # lesen, ergibt -8
+
+class MyPositiveNumber:
+  def __init__(self, r=0):
+    self.r = r  # benutzt schon setter unten
+
+  @property     # getter
+  def r(self):
+    return self._r
+
+  @r.setter     # setter
+  def r(self, val):
+    self._r = val if val > 0 else 0
+
+num = MyPositiveNumber(3)
+num.r = -8      # ruft setter auf
+print(num.r)    # ruft getter auf, ergibt: 0
+
+# %% Vererbung
+class MyPositiveComplex(MyPositiveNumber): # erbt von MyPositiveNumber
+    def __init__(self, r=0, i=0):
+        super().__init__(r)                # rufe Konstruktor von MyPositiveNumber auf
+        self.i = i                         # benutzt schon setter unten
+
+    @property                              # getter
+    def i(self):
+        return self._i
+
+    @i.setter                              # setter
+    def i(self, val):
+        self._i = val if val > 0 else 0
+
+c = MyPositiveComplex(-8, 1)
+c.i = -5                                   # ruft setter auf
+print(f'{c.r} + {c.i}j')                   # ruft getter auf, ergibt: 0 + 0j
+
+# %% Alternativer Konstruktor mit Klassenmethode
+class Text:
+    def __init__(self, text):
+        self.text = text
+
+    @classmethod
+    def from_file(cls, path):
+        with open(path) as f:
+            return cls(f.read())
+
+class GradedText(Text):
+    def __init__(self, text, grade=None):
+        super().__init__(text)
+        self.grade = grade
+
+file = 'data.csv'
+t =  Text.from_file(file)
+print(t.text)
+print(type(t))
+
+gt = GradedText.from_file(file)
+print(gt.text, gt.grade)
+print(type(gt))
diff --git a/02-python-vertiefung/folien-code/mymodule.py b/02-python-vertiefung/folien-code/mymodule.py
new file mode 100644
index 0000000000000000000000000000000000000000..9537d8fd533f0e880f84d2dc8f96029c6c65a347
--- /dev/null
+++ b/02-python-vertiefung/folien-code/mymodule.py
@@ -0,0 +1,5 @@
+'''This is my example module'''
+__version__ = '1.3.4'
+print('Hello Module')
+def say_hello(name):
+    print('Hello', name)
\ No newline at end of file
diff --git a/02-python-vertiefung/folien-code/mypackage/__init__.py b/02-python-vertiefung/folien-code/mypackage/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..18cf26245e6f65044be94e661ed40a65dd167475
--- /dev/null
+++ b/02-python-vertiefung/folien-code/mypackage/__init__.py
@@ -0,0 +1 @@
+from mypackage.mymod import say_hello
diff --git a/02-python-vertiefung/folien-code/mypackage/mymod.py b/02-python-vertiefung/folien-code/mypackage/mymod.py
new file mode 100644
index 0000000000000000000000000000000000000000..f93810baefb19ba04f3c202d6e1fa3ef001a7c18
--- /dev/null
+++ b/02-python-vertiefung/folien-code/mypackage/mymod.py
@@ -0,0 +1,3 @@
+print('Hello Module')
+def say_hello(name):
+    print('Hello', name)
\ No newline at end of file
diff --git a/02-python-vertiefung/folien-code/mypackage/subpackage/more.py b/02-python-vertiefung/folien-code/mypackage/subpackage/more.py
new file mode 100644
index 0000000000000000000000000000000000000000..d0143b19e1b622aca2bf948746fdfca83f62f759
--- /dev/null
+++ b/02-python-vertiefung/folien-code/mypackage/subpackage/more.py
@@ -0,0 +1,2 @@
+def say_bye():
+    print('bye')
diff --git a/03-numpy-und-matplotlib/folien-code/autos.csv b/03-numpy-und-matplotlib/folien-code/autos.csv
new file mode 100644
index 0000000000000000000000000000000000000000..6ffed5d9d0763ac6fcc0fca8390422e21655b91d
--- /dev/null
+++ b/03-numpy-und-matplotlib/folien-code/autos.csv
@@ -0,0 +1,616 @@
+Marke,Modell,Grundpreis,Leistung_kW,Hubraum,Leergewicht,Verbrauch_kombi,Tueranzahl,Fahrzeugklasse
+Bugatti,Chiron,2856000,1103,7993,2070,22.5,2,6
+Koenigsegg,Agera RS,2112275,865,5032,1395,14.7,2,6
+Lamborghini,Centenario LP770-4,2082500,566,6498,1520,16,2,6
+Lamborghini,Centenario Roadster LP770-4,2082500,566,6498,1570,16,2,6
+smart,forfour BRABUS,21225,80,898,1095,4.6,5,1
+Abarth,595C,21090,107,1368,1150,6.5,2,1
+Abarth,595,18490,107,1368,1110,6,3,1
+VW,up! GTI,16975,85,999,1070,4.8,3,1
+Opel,ADAM ROCKS 1.2,15780,51,1229,1086,5.3,3,1
+Fiat,500C 1.2 8V,15190,51,1242,980,4.9,2,1
+VW,cross up! 1.0 BMT,14500,55,999,1009,4.3,5,1
+Fiat,Panda Cross 1.2 8V,13490,51,1242,1015,5.1,5,1
+Opel,KARL ROCKS 1.0,12800,55,999,939,4.7,5,1
+Peugeot,108 Top! 1.0 VTi 68,12600,51,998,915,4.1,3,1
+Fiat,500 1.2 8V,12590,51,1242,940,4.9,3,1
+Suzuki,Ignis 1.2,12540,66,1242,885,4.6,5,1
+Citroen,C1 Airscape VTi 68,12400,51,998,915,4.1,3,1
+Opel,ADAM 1.2,12135,51,1229,1086,5.3,3,1
+smart,forfour 1.0,11765,52,999,975,4.2,5,1
+Hyundai,i10 1.0,9990,49,998,1008,4.7,5,1
+KIA,Picanto 1.0,9990,49,998,935,4.4,5,1
+Peugeot,108 1.0 VT 68,9990,51,998,915,4.1,3,1
+VW,up! 1.0,9975,44,999,926,4.4,3,1
+Toyota,Aygo 1.0,9950,51,998,915,4.1,3,1
+Fiat,Panda 1.2 8V,9850,51,1242,1015,5.1,5,1
+Skoda,Citigo 1.0,9770,44,999,929,4.4,3,1
+Renault,Twingo SCe 70,9750,51,999,939,5,5,1
+Suzuki,Celerio 1.0,9690,50,998,880,4.3,5,1
+Opel,KARL 1.0,9560,55,999,939,4.5,5,1
+Citroen,C1 VTi 68,9090,51,998,915,4.1,3,1
+SEAT,Mii 1.0,8990,44,999,929,4.4,3,1
+MINI,John Cooper Works Cabrio,34300,170,1998,1385,6.5,2,2
+Nissan,Juke Nismo RS,31915,157,1618,1469,7.3,5,2
+Audi,S1 Sportback,31300,170,1984,1415,7.1,5,2
+Toyota,Yaris GRMN,30800,156,1798,1135,7.5,5,2
+MINI,John Cooper Works,30700,170,1998,1280,6.3,3,2
+Audi,S1,30450,170,1984,1390,7,3,2
+DS Automobiles,DS 3 Performance,26990,153,1598,1250,5.4,3,2
+Opel,Corsa OPC,24930,152,1598,1293,7.5,3,2
+Peugeot,208.,23990,153,1598,1235,5.4,3,2
+VW,Polo GTI,23950,147,1984,1355,5.9,5,2
+Renault,Clio R.S.,23390,147,1618,1279,5.9,5,2
+MINI,One Cabrio,22500,75,1198,1280,5,2,2
+Honda,HR-V 1.5 i-VTEC,20690,96,1498,1312,5.6,5,2
+DS Automobiles,DS 3 Cabrio PureTech 82,19940,60,1199,1110,4.9,2,2
+Jeep,Renegade 1.6 E-torQ,19900,81,1598,1395,6,5,2
+Opel,Mokka X 1.6 Start&Stop,18990,85,1598,1355,6.7,5,2
+Ford,EcoSport 1.0 EcoBoost,18590,92,998,1337,5.2,5,2
+Citroen,C3 Picasso VTi 95,18190,70,1397,1276,5.9,5,2
+Hyundai,i20 Coupee 1.0 T-GDI,18100,88,998,1145,4.8,3,2
+Ford,EcoSport 1.5 Ti-VCT,17990,82,1498,1314,6.3,5,2
+Mazda,CX-3 SKYACTIV-G 120,17990,88,1998,1230,5.9,5,2
+Suzuki,Vitara 1.6,17990,88,1586,1150,5.3,5,2
+Peugeot,2008 PureTech 82,17550,60,1199,1120,4.9,5,2
+Hyundai,Kona 1.0 T-GDI,17500,88,998,1233,5.2,5,2
+MINI,One First,17350,55,1198,1225,5.2,5,2
+Hyundai,i20 Active 1.0 T-GDI blue,17300,74,998,1160,4.5,5,2
+KIA,Soul 1.6 GDI,17240,97,1591,1275,6.5,5,2
+Audi,A1 Sportback 1.0 TFSI ultra,17100,60,999,1135,4.2,5,2
+Fiat,500L 1.4 16V,16990,70,1368,1330,6.2,5,2
+Fiat,500L Wagon 1.4 16V,16990,70,1368,1350,6.1,5,2
+Opel,Crossland X 1.2,16990,60,1199,1136,5.2,5,2
+Ford,B-MAX 1.4,16800,66,1388,1275,6,5,2
+Honda,Jazz 1.3 i-VTEC,16640,75,1318,1138,5,5,2
+Fiat,500L Urban 1.4 16V,16490,70,1368,1320,6.1,5,2
+MINI,One First,16400,55,1198,1165,5.1,3,2
+Fiat,500X 1.6 E-torQ,16290,81,1598,1350,6.4,5,2
+Audi,A1 1.0 TFSI ultra,16250,60,999,1110,4.2,3,2
+DS Automobiles,DS 3 PureTech 82,15990,60,1199,1049,4.6,3,2
+Nissan,Juke 1.6,15990,69,1598,1163,6,5,2
+SEAT,Arona 1.0 EcoTSI,15990,70,999,1165,4.9,5,2
+SsangYong,Tivoli 1.6 e-XGi 160,15990,94,1597,1270,6.6,5,2
+Renault,Captur ENERGY TCe 90,15890,66,898,1259,5.1,5,2
+Hyundai,ix20 1.4 blue,15790,66,1396,1253,5.6,5,2
+KIA,Stonic 1.2,15790,62,1248,1145,5.2,5,2
+Alfa Romeo,MiTo 1.4 8V,15700,57,1368,1155,5.6,3,2
+Suzuki,Jimny 1.3,15590,62,1328,1135,7.1,3,2
+Citroen,C3 Aircross PureTech 82,15290,60,1199,1163,5.1,5,2
+Ford,Tourneo Courier 1.0 EcoBoost,15260,74,998,1260,5.3,5,2
+Ford,Transit Courier Kombi 1.0 EcoBoost,15220,74,998,1260,5.3,4,2
+Fiat,Fiorino Kombi 1.4 8V,15161,57,1368,1255,6.9,4,2
+KIA,Venga 1.4,14890,66,1396,1253,6,5,2
+Citroen,C4 Cactus PureTech 75,13990,55,1199,1040,4.6,5,2
+Suzuki,Swift 1.2 Dualjet,13790,66,1242,915,4.3,5,2
+Suzuki,Baleno 1.2 Dualjet,13790,66,1242,940,4.2,5,2
+Skoda,Fabia Combi 1.0 MPI,13450,55,999,1104,4.8,5,2
+Nissan,Micra 1.0,12990,52,998,977,4.6,5,2
+Renault,Clio Grandtour 1.2 16V 75,12990,54,1149,1141,5.6,5,2
+VW,Polo 1.0 MPI,12975,48,999,1105,4.7,5,2
+Ford,Fiesta 1.1,12950,51,1084,1108,4.7,3,2
+Mazda,2 SKYACTIV-G 75,12890,55,1496,1045,4.7,5,2
+Fiat,Punto 1.2 8V,12790,51,1242,1105,5.4,5,2
+Peugeot,208 1.2 PureTech 68,12750,50,1199,1035,4.7,3,2
+Toyota,Yaris 1.0,12540,51,998,1055,4.3,3,2
+Fiat,Qubo 1.4 8V,12490,57,1368,1255,6.9,5,2
+SEAT,Ibiza 1.0 MPI,12490,48,999,1091,4.9,5,2
+Skoda,Fabia 1.0 MPI,12150,44,999,1080,4.8,5,2
+Opel,Corsa 1.2,12135,51,1229,1120,5.4,3,2
+Hyundai,i20 1.2,12015,55,1248,1055,5.1,5,2
+Citroen,C3 PureTech 68,11990,50,1199,1051,4.7,5,2
+Renault,Clio 1.2 16V 75,11990,54,1149,1134,5.6,5,2
+KIA,Rio 1.2,11690,62,1248,1110,4.8,5,2
+Lada,Kalina Cross 1.6 8V,10200,64,1596,1110,6.6,5,2
+Dacia,Sandero Stepway TCe 90 Start&Stop,9990,66,898,1115,5.1,5,2
+Ford,Ka+ 1.2 Ti-VCT,9990,51,1198,1055,5,5,2
+Mitsubishi,Space Star 1.0,9290,52,999,920,4.2,5,2
+Lada,Kalina Kombi 1.6 8V,8260,64,1596,1110,6.6,5,2
+Lada,Kalina 1.6 8V,7460,64,1596,1080,6.6,5,2
+Dacia,Sandero SCe 75,6990,54,998,1044,5.2,5,2
+smart,fortwo cabrio BRABUS,23675,80,898,1040,4.6,2,1
+smart,fortwo Coupee BRABUS,20415,80,898,995,4.5,3,1
+smart,fortwo cabrio 1.0,14365,52,999,940,4.3,2,1
+smart,fortwo Coupee 1.0,11105,52,999,890,4.1,3,1
+Morgan,Aero Supersports 4.8 V8,168000,270,4799,1220,11.2,2,4
+BMW,M3 CS,117600,338,2979,1660,8.3,4,4
+BMW,M4 CS Coupee,116900,338,2979,1655,8.4,2,4
+Lotus,Evora 400,96000,298,3456,1415,9.7,2,4
+Alfa Romeo,Stelvio Quadrifoglio,89000,375,2891,1905,9,5,4
+Porsche,Macan Turbo,84586,294,3604,2000,9,5,4
+BMW,M4 Cabrio,84500,317,2979,1825,9.1,2,4
+BMW Alpina,B4 S Bi-Turbo Cabrio,81400,324,2979,1915,8.3,2,4
+Audi,RS5 Coupee,80900,331,2894,1730,8.7,2,4
+Audi,RS4 Avant,79800,331,2894,1790,8.8,5,4
+BMW,M4 Coupee,78200,317,2979,1572,8.8,2,4
+BMW,M3,77500,317,2979,1595,8.8,4,4
+Lexus,RC F,75900,351,4969,1840,10.8,3,4
+BMW Alpina,B4 S Bi-Turbo Coupee,75300,324,2979,1690,7.9,2,4
+Lotus,Exige Coupee,75200,258,3456,1110,10.1,2,4
+Lotus,Exige Roadster,75200,258,3456,1110,10.1,2,4
+Porsche,Macan GTS,74828,265,2997,1970,8.9,5,4
+BMW Alpina,B3 S Bi-Turbo Touring,74700,324,2979,1780,8.1,5,4
+BMW Alpina,B3 S Bi-Turbo,72900,324,2979,1705,7.9,4,4
+Alfa Romeo,Giulia Quadrifoglio,72800,375,2891,1670,8.5,4,4
+Cadillac,ATS-V Coupee,72500,346,3564,1775,11.4,3,4
+Alfa Romeo,4C Spider,72000,177,1742,1015,6.9,2,4
+Cadillac,ATS-V,69900,346,3564,1775,11.6,4,4
+Audi,TT RS Roadster,69200,294,2480,1605,8.3,2,4
+Mercedes,C 43 AMG Cabriolet,68455,270,2996,1870,8.3,2,4
+Audi,S5 Cabriolet,68050,260,2995,1915,7.9,2,4
+Morgan,Roadster 3.7 V6,68000,209,3721,950,9.8,2,4
+Audi,TT RS Coupee,66400,294,2480,1515,8.2,3,4
+Mercedes,GLC Coupee 43 AMG,65807,270,2996,1855,8.4,5,4
+Audi,SQ5 TFSI,65400,260,2995,1945,8.3,5,4
+Alfa Romeo,4C,63500,177,1742,970,6.8,2,4
+Audi,S5 Sportback,62750,260,2995,1735,7.5,5,4
+Audi,S5 Coupee,62750,260,2995,1690,7.5,2,4
+Mercedes,GLC 43 AMG,62178,270,2996,1845,8.3,5,4
+Audi,S4 Avant,61900,260,2995,1750,7.7,5,4
+Mercedes,C 43 AMG T-Modell,61850,270,2996,1735,7.9,5,4
+Mercedes,C 43 AMG Coupee,61761,270,2996,1735,7.8,2,4
+Mercedes,C 43 AMG,60184,270,2996,1690,7.8,4,4
+Audi,S4,60050,260,2995,1705,7.5,4,4
+Mercedes,SLC 43 AMG,60036,270,2996,1595,7.8,2,4
+Alpine,A110,58000,185,1798,1178,6.1,2,4
+Land Rover,Range Rover Velar P250,56400,184,1998,1804,7.6,5,4
+Porsche,Macan,56264,185,1984,1845,7.2,5,4
+Audi,TTS Roadster,53350,228,1984,1525,7.3,2,4
+Jaguar,F-Pace 25t,51160,184,1997,1760,7.4,5,4
+Audi,TTS Coupee,50550,228,1984,1440,7.1,3,4
+Audi,Q5 2.0 TFSI,50500,185,1984,1795,6.8,5,4
+BMW,X4 xDrive20i,49850,135,1997,1810,7.2,5,4
+Mercedes,GLC Coupee 250,49837,155,1991,1785,6.9,5,4
+Opel,Insignia Sports Tourer GSi 2.0 DI Turbo Start&Stop,48800,191,1998,1716,8.7,5,4
+Audi,A4 Allroad 2.0 TFSI,48750,185,1984,1655,6.4,5,4
+Volvo,XC60 T5,48650,184,1969,1915,7.4,5,4
+Jeep,Cherokee 3.2 V6 Pentastar,48000,200,3239,2036,9.6,5,4
+Opel,Insignia Grand Sport GSi 2.0 DI Turbo Start&Stop,47800,191,1998,1683,8.6,5,4
+BMW,420i Cabrio,47700,135,1998,1775,6.2,2,4
+Volvo,S60 Cross Country T5,47050,180,1969,1722,7.4,4,4
+Nissan,370Z Nismo,46880,253,3696,1496,10.6,3,4
+Volvo,V60 Cross Country T5,45950,180,1969,1776,7.4,5,4
+Land Rover,Discovery Sport Si4,45750,177,1998,1796,8,5,4
+Mercedes,GLC 250,45315,155,1991,1735,6.5,5,4
+Infiniti,Q50 2.0t,44900,155,1991,1587,6.3,4,4
+Jeep,Wrangler Unlimited 3.6 V6,44900,209,3604,1995,11.4,5,4
+Infiniti,Q60 2.0t,44500,155,1991,1722,6.8,2,4
+BMW,X3 xDrive20i,44400,135,1998,1790,7.1,5,4
+Audi,A5 Cabriolet 2.0 TFSI,44000,140,1984,1675,5.9,2,4
+KIA,Stinger 2.0 T-GDI,43990,188,1998,1717,7.9,5,4
+VW,Passat Alltrack 2.0 TSI BMT,43925,162,1984,1677,6.9,5,4
+Morgan,4/4 1.8 16V,43009,82,1595,800,8.2,2,4
+Mercedes,C 180 Cabriolet,42727,115,1595,1600,6,2,4
+Infiniti,Q50 2.0t,42500,155,1991,1585,6.3,4,4
+Alfa Romeo,Stelvio 2.0 Turbo 16V,42200,147,1995,1735,7,5,4
+Jeep,Wrangler 3.6 V6,41900,209,3604,1828,11,3,4
+Renault,Espace ENERGY TCe 225,40900,165,1798,1685,6.8,5,4
+BMW,420i Coupee,40400,135,1998,1550,5.8,2,4
+BMW,420i Gran Coupee,40400,135,1998,1595,5.8,5,4
+Cadillac,ATS Coupee 2.0 Turbo,40400,203,1998,1591,7.7,3,4
+BMW,320i Gran Turismo,40200,135,1998,1655,6.1,5,4
+Nissan,370Z Roadster,40130,241,3696,1496,11.2,2,4
+DS Automobiles,DS 7 Crossback PureTech 225,38990,165,1598,1500,5.9,5,4
+Alfa Romeo,Giulia 2.0 Turbo 16V,38500,147,1995,1504,6,4,4
+Audi,A5 Sportback 2.0 TFSI,38050,140,1984,1505,5.8,5,4
+Audi,A5 Coupee 2.0 TFSI,38050,140,1984,1465,5.6,2,4
+Cadillac,ATS 2.0 Turbo,37400,203,1998,1593,7.6,4,4
+Jaguar,XE 20t,36960,147,1997,1540,6.3,4,4
+Subaru,Outback 2.5i,36900,129,2498,1582,7,5,4
+Mercedes,C 180 Coupee,36033,115,1595,1475,5.3,2,4
+Audi,TT Roadster 1.8 TFSI,35550,132,1798,1375,5.9,2,4
+Mercedes,SLC 180,35349,115,1595,1435,5.6,2,4
+Skoda,Kodiaq Scout 1.4 TSI ACT,35050,110,1395,1610,6.8,5,4
+Opel,Insignia Country Tourer 1.5 DI Turbo Start&Stop,34885,121,1490,1522,6.4,5,4
+BMW,318i Touring,34550,100,1499,1545,5.4,5,4
+DS Automobiles,DS 5 THP 165 Stop&Start,34390,121,1598,1504,5.9,5,4
+Nissan,370Z Coupee,34130,241,3696,1496,10.6,3,4
+Audi,A4 Avant 1.4 TFSI,33700,110,1395,1445,5.4,5,4
+Mercedes,C 160 T-Modell,33534,95,1595,1470,5.4,5,4
+VW,Sharan 1.4 TSI BMT,33325,110,1395,1703,6.4,5,4
+Ford,Galaxy 1.5 EcoBoost Start/Stopp,33310,118,1498,1708,6.5,5,4
+Audi,TT Coupee 1.8 TFSI,33150,132,1798,1285,5.8,3,4
+BMW,318i,32850,100,1499,1475,5.1,4,4
+Subaru,BRZ 2.0i,32400,147,1998,1243,7.8,2,4
+Skoda,Octavia Scout 1.8 TSI,32110,132,1798,1522,6.8,5,4
+Volvo,V60 T2,32100,90,1498,1680,5.9,5,4
+Mercedes,C 160,31868,95,1595,1395,5.2,4,4
+Audi,A4 1.4 TFSI,31850,110,1395,1395,5.2,4,4
+Skoda,Octavia Combi RS,31590,169,1984,1442,6.5,5,4
+Hyundai,Santa Fe 2.4 GDI,31190,138,2359,1708,9.4,5,4
+Skoda,Octavia RS,30890,169,1984,1420,6.5,5,4
+Peugeot,508 SW THP 165 STOP&START,30850,121,1598,1495,5.8,5,4
+Renault,Talisman Grandtour Energy TCe 150,30800,110,1618,1565,5.8,5,4
+Volvo,S60 T2,30500,90,1498,1632,5.8,4,4
+SEAT,Alhambra 1.4 TSI Start&Stop,30435,110,1395,1703,6.4,5,4
+Ford,S-MAX 1.5 EcoBoost Start/Stopp,30400,118,1498,1645,6.5,5,4
+Subaru,Levorg 1.6 Turbo,29990,125,1600,1537,6.9,5,4
+Toyota,GT86 2.0,29990,147,1998,1305,7.8,2,4
+VW,Tiguan Allspace 1.4 TSI ACT,29975,110,1395,1570,6.1,5,4
+Peugeot,508 THP 165 STOP&START,29800,121,1598,1475,5.8,4,4
+Renault,Talisman Energy TCe 150,29800,110,1618,1505,5.6,4,4
+Toyota,RAV4 2.0,27990,112,1987,1565,6.7,5,4
+VW,Passat Variant 1.4 TSI BMT,27875,92,1395,1394,5.3,5,4
+Opel,Cascada 1.4 Turbo,27545,88,1364,1701,6.7,2,4
+Ford,Mondeo Turnier 1.0 EcoBoost,26990,92,998,1476,5.3,5,4
+VW,Passat 1.4 TSI BMT,26800,92,1395,1367,5.3,4,4
+Opel,Insignia Sports Tourer 1.5 DI Turbo Start&Stop,26730,103,1490,1487,6,5,4
+Skoda,Kodiaq 1.4 TSI,26150,92,1395,1502,6,5,4
+Ford,Mondeo 1.0 EcoBoost,25990,92,998,1455,5.2,5,4
+KIA,Optima Sportswagon 2.0,25990,120,1999,1550,7.6,5,4
+Subaru,Forester 2.0X,25900,110,1995,1478,6.9,5,4
+Mazda,6 SKYACTIV-G 145 i-ELOOP,25890,107,1998,1375,5.5,4,4
+Mazda,6 Kombi SKYACTIV-G 145 i-ELOOP,25890,107,1998,1380,5.6,5,4
+Toyota,Avensis Touring Sports 1.6,25740,97,1598,1460,6.2,5,4
+Opel,Insignia Grand Sport 1.5 DI Turbo Start&Stop,25630,103,1490,1441,5.9,5,4
+Hyundai,i40 Kombi 1.6 GDI blue,25490,99,1591,1503,6.1,5,4
+Nissan,X-Trail 1.6 DIG-T,25440,120,1618,1505,6.2,5,4
+KIA,Optima 2.0,25090,120,1999,1530,7.4,4,4
+Nissan,X-Trail 1.6 DIG-T,24990,120,1618,1505,6.2,5,4
+Peugeot,5008 1.2 PureTech 130,24900,96,1199,1385,5.1,5,4
+Toyota,Avensis 1.6,24740,97,1598,1430,6.1,4,4
+Honda,CR-V 2.0,23990,114,1997,1531,7.2,5,4
+Mitsubishi,Outlander 2.0 ClearTec,21990,110,1998,1497,6.7,5,4
+Nissan,Evalia 16V 110,20690,81,1598,1386,7.3,5,4
+Nissan,NV200 Kombi 16V 110,19921,81,1598,1351,7.3,5,4
+Skoda,Octavia Combi 1.2 TSI,18150,63,1197,1247,4.8,5,4
+Skoda,Octavia 1.2 TSI,17450,63,1197,1225,4.8,5,4
+Nissan,GT-R Nismo,184950,441,3799,1800,11.8,3,5
+Jaguar,F-Type SVR Cabriolet 5.0 V8 Kompressor,146400,423,5000,1720,11.3,2,5
+Jaguar,F-Type SVR Coupee 5.0 V8 Kompressor,139400,423,5000,1705,11.3,3,5
+Porsche,Cayenne Turbo,138850,404,3996,2250,11.9,5,5
+Porsche,Cayenne Turbo,132781,382,4806,2260,11.2,5,5
+BMW,X6 M,124200,423,4395,2265,11.1,5,5
+Mercedes,CLS 63 AMG Shooting Brake,122630,410,5461,2025,10.6,5,5
+Audi,RS7 performance cod Sportback,122200,445,3993,2005,9.5,5,5
+BMW,X5 M,120700,423,4395,2350,11.1,5,5
+BMW,M5,117900,441,4395,1930,10.5,4,5
+Mercedes,CLS 63 AMG Coupee,116918,410,5461,1870,9.9,4,5
+BMW Alpina,B5 Bi-Turbo Touring,115300,447,4395,2120,10.4,5,5
+Audi,RS6 cod Avant,112000,412,3993,2025,9.8,5,5
+BMW Alpina,B5 Bi-Turbo,112000,447,4395,2015,10.3,4,5
+Porsche,Cayenne GTS,102555,324,3604,2185,9.8,5,5
+Lexus,GS F,100500,351,4969,1865,11.2,4,5
+Nissan,GT-R,99900,419,3799,1827,11.8,3,5
+Cadillac,CTS-V,98900,477,6162,1925,13,4,5
+Dodge,Charger SRT 392,85900,362,6417,2000,15.5,4,5
+Audi,S7 cod Sportback,84600,331,3993,2030,9.3,5,5
+Dodge,Challenger SRT 392,82900,362,6417,2000,15.5,2,5
+Audi,S6 cod Avant,80150,331,3993,2035,9.4,5,5
+Mercedes,E 43 AMG T-Modell,78177,295,2996,1930,8.6,5,5
+Porsche,718 Boxster GTS,78160,269,2497,1450,9,2,5
+Audi,S6 cod,77650,331,3993,1970,9.2,4,5
+Mercedes,GLE Coupee 43 AMG,77469,270,2996,2240,8.9,5,5
+Porsche,718 Cayman GTS,76137,269,2497,1450,9,2,5
+Maserati,Levante,76000,257,2979,2109,10.7,4,5
+Mercedes,E 43 AMG,75387,295,2996,1840,8.2,4,5
+Porsche,Cayenne,74828,250,2995,1985,9,5,5
+BMW,X6 xDrive35i,72000,225,2979,2100,8.5,5,5
+Mercedes,GLE 43 AMG,70746,270,2996,2180,8.6,5,5
+Maserati,Ghibli,70250,257,2979,1810,8.9,4,5
+Maserati,Ghibli,69200,243,2979,1810,8.9,4,5
+Mercedes,GLE Coupee 400,68306,245,2996,2180,8.7,5,5
+BMW,X5 xDrive35i,66400,225,2979,2105,8.5,5,5
+Jaguar,F-Type Cabriolet P300,66200,221,1997,1545,7.2,2,5
+Mercedes,CLS 400 Shooting Brake,65212,245,3498,1845,7.3,5,5
+Mercedes,CLS 400 Coupee,63427,245,3498,1775,7.4,4,5
+BMW,630i Gran Turismo,62300,190,1998,1720,6.2,5,5
+Dodge,RAM 1500 Quad Cab 5.7 V8,61900,295,5700,2556,12.8,4,5
+Mercedes,GLE 400,61583,245,2996,2130,8.5,5,5
+Infiniti,Q70 3.7,60750,235,3696,1826,10.8,4,5
+Volvo,XC90 T5,59850,184,1969,2112,7.8,5,5
+Jaguar,F-Type Coupee P300,59200,221,1997,1525,7.2,3,5
+Volvo,V90 Cross Country T5,57800,184,1969,1937,7.3,5,5
+Porsche,718.,54717,220,1988,1410,7.4,2,5
+Land Rover,Discovery Si4,54700,221,1997,2093,9.4,5,5
+Mercedes,E 200 Cabriolet,54228,135,1991,1755,6.2,3,5
+Infiniti,QX70 3.7,53800,235,3696,2012,12.1,5,5
+Porsche,718.,52694,220,1988,1410,7.4,2,5
+Jeep,Grand Cherokee 3.6 V6,51900,213,3604,2266,10,5,5
+Jaguar,XF Sportbrake 25t,51060,184,1997,1760,6.8,5,5
+Lexus,RX 200t,49900,175,1998,1885,7.8,5,5
+Cadillac,XT5 3.6 V6,49300,231,3649,1954,10,5,5
+BMW,520i Touring,49100,135,1998,1705,5.8,5,5
+Mercedes,E 200 T-Modell,48903,135,1991,1705,6.2,5,5
+Chevrolet,Camaro Cabriolet 2.0 Turbo,48000,202,1998,1659,8.1,2,5
+BMW,520i,46600,135,1998,1605,5.4,4,5
+Mercedes,E 200 Coupee,46494,135,1991,1645,6.5,3,5
+Cadillac,CTS 2.0 Turbo,45350,203,1998,1659,7.8,4,5
+Audi,A6 Avant 1.8 TFSI ultra,45200,140,1798,1710,5.9,5,5
+Jaguar,XF 20t,45060,147,1997,1635,6.8,4,5
+Volvo,V90 T4,44900,140,1969,1851,6.9,5,5
+VW,T6 California 2.0 TSI BMT,44833,110,1984,2264,9.5,4,5
+Ford,Mustang Convertible 2.3 EcoBoost,43500,213,2261,1715,9.1,2,5
+Volvo,S90 T4,43450,140,1969,1800,6.7,4,5
+Mercedes,E 200,43019,135,1991,1575,6.1,4,5
+Audi,A6 1.8 TFSI ultra,42700,140,1798,1645,5.7,4,5
+Ford,Mustang Convertible 2.3 EcoBoost,42500,233,2261,1715,8.2,2,5
+Chevrolet,Camaro Coupee 2.0 Turbo,40400,202,1998,1539,8,2,5
+Ford,Mustang Fastback 2.3 EcoBoost,39000,213,2261,1655,9,2,5
+VW,T6 Caravelle 2.0 TSI BMT,38645,110,1984,1862,9.1,4,5
+Ford,Mustang Fastback 2.3 EcoBoost,38000,233,2261,1655,8,2,5
+VW,T6 Multivan 2.0 TSI BMT,36902,110,1984,2007,9.2,4,5
+VW,Arteon 1.5 TSI ACT,35325,110,1498,1504,5.1,5,5
+VW,T6 Transporter Kombi 2.0 TSI BMT Normaldach,33832,110,1984,1862,9.1,4,5
+Skoda,Superb Combi 1.4 TSI,26750,92,1395,1395,5.6,5,5
+Skoda,Superb 1.4 TSI,25750,92,1395,1375,5.6,5,5
+Mercedes,Maybach G 650,749700,463,5980,2580,17,5,6
+Ford,GT,500000,475,3497,1385,14.9,2,6
+Rolls-Royce,Phantom 6.8 V12,446250,420,6749,2560,13.9,4,6
+Lamborghini,Aventador S Roadster LP740-4,373262,544,6498,1625,16.9,2,6
+Mercedes,Maybach S 650 Cabriolet,357000,463,5980,2115,12,2,6
+Lamborghini,Aventador S LP740-4,335055,544,6498,1575,16.9,2,6
+Rolls-Royce,Dawn 6.6 V12,329630,420,6592,2560,14.2,2,6
+Bentley,Mulsanne,297191,377,6752,2685,15,4,6
+Bentley,Continental Supersports Convertible,291253,522,5998,2455,15.9,2,6
+Rolls-Royce,Wraith 6.6 V12,285898,465,6592,2435,14.3,2,6
+Porsche,911 GT2 RS,285220,515,3800,1545,11.8,2,6
+Ferrari,812.,282934,588,6496,1630,14.9,2,6
+Rolls-Royce,Ghost 6.6 V12,277657,420,6592,2435,14.3,4,6
+Aston Martin,Vanquish Volante,268995,424,5935,1919,12.8,3,6
+Bentley,Continental Supersports,264775,522,5998,2280,15.7,2,6
+Mercedes,S 65 AMG Cabriolet,257457,463,5980,2255,12,2,6
+Aston Martin,Vanquish,253995,424,5935,1814,12.8,3,6
+McLaren,720S,247350,527,3994,1322,10.7,2,6
+Ferrari,F488 Spider,236750,493,3902,1525,11.4,2,6
+Mercedes,G 500 4x4,231693,310,3982,3021,13.8,5,6
+Ferrari,GTC4Lusso T,226246,449,3855,1870,11.6,2,6
+Ferrari,F488 GTB,212653,493,3902,1475,11.4,2,6
+McLaren,570S Spider,208975,419,3799,1573,10.7,2,6
+Bentley,Bentayga W12,208488,447,5950,2440,12.8,5,6
+Lamborghini,Urus,204000,478,3996,2200,12.7,5,6
+Aston Martin,DB11 Volante V8,199000,375,3982,1870,9.9,3,6
+Bentley,Continental GT W12,198492,467,5950,2244,12.2,2,6
+Lamborghini,Huracn Spyder LP580-2,196350,426,5204,1509,12.1,2,6
+McLaren,570GT,195350,419,3799,1515,10.7,2,6
+Aston Martin,Rapide S,193995,411,5935,2065,12.9,5,6
+Aston Martin,V12 Vantage S Roadster,192741,421,5935,1745,14.7,3,6
+Bentley,Continental GT Convertible V8,192066,373,3993,2470,10.9,2,6
+Porsche,911 Turbo Cabriolet,190020,397,3800,1740,9.3,2,6
+Mercedes,S 63 AMG Cabriolet,190013,430,5461,2185,10.4,2,6
+Porsche,911.,189544,368,3996,1445,13.3,2,6
+McLaren,570S,185400,419,3799,1515,10.7,2,6
+Ferrari,California T,184689,412,3855,1730,10.7,2,6
+Aston Martin,DB11 V8,184000,375,3982,1760,9.9,3,6
+Bentley,Flying Spur V8,183855,373,3993,2417,10.9,4,6
+Donkervoort,D8 GTO-RS,182070,284,2480,695,8,2,6
+Aston Martin,V12 Vantage S,179950,421,5935,1680,17,3,6
+Lamborghini,Huracn LP580-2,178500,426,5204,1389,11.9,2,6
+Mercedes,S 63 AMG Coupee,177310,450,3982,2080,9.3,2,6
+Porsche,911 Turbo Coupee,176930,397,3800,1670,9.1,2,6
+Mercedes,S 63 AMG Coupee,175436,430,5461,2070,10.1,2,6
+Bentley,Continental GT V8,174573,373,3993,2370,10.6,2,6
+McLaren,540C,163200,397,3799,1446,10.7,2,6
+Mercedes,SL 63 AMG,161959,430,5461,1845,9.8,2,6
+Mercedes,S 63 AMG,160293,450,3982,2070,8.9,4,6
+Porsche,Panamera Sport Turismo Turbo,158604,404,3996,2110,9.4,5,6
+Porsche,Panamera Turbo,155748,404,3996,2070,9.3,5,6
+Audi,R8 Spyder 5.2 FSI V10,153000,397,5204,1755,12.6,2,6
+Porsche,911.,152416,368,3996,1488,12.9,2,6
+BMW Alpina,B7 Bi-Turbo,149400,447,4395,2110,10.4,4,6
+Porsche,911.,146228,331,2981,1660,9.7,2,6
+Mercedes,G 63 AMG,145359,420,5461,2550,13.8,5,6
+Maserati,GranCabrio Sport,144320,338,4691,1980,14.5,2,6
+Jaguar,XJR575,143900,423,5000,1875,11.1,4,6
+Mercedes,S 500 Cabriolet,140545,335,4663,2115,8.5,2,6
+Audi,R8 Coupee 5.2 FSI V10,140000,397,5204,1665,12.4,2,6
+Mercedes,Maybach S 560,139700,345,3982,2240,8.8,4,6
+Porsche,911 Carrera Cabriolet,138850,331,2981,1595,9.4,2,6
+Donkervoort,D8 GTO-S,138040,254,2480,740,8,2,6
+BMW,M6 Cabrio,137200,412,4395,2055,10.3,2,6
+BMW Alpina,B6 Bi-Turbo Cabriolet,137200,441,4395,2095,9.6,2,6
+BMW Alpina,B6 Bi-Turbo Gran Coupee,135800,441,4395,2030,10.4,4,6
+Aston Martin,V8 Vantage S Roadster,135520,321,4735,1710,13.8,2,6
+Mercedes,GLS 63 AMG,135482,430,5461,2580,12.3,5,6
+BMW,M6 Gran Coupee,134500,412,4395,1950,9.9,4,6
+Land Rover,Range Rover Sport SVR,132200,423,5000,2310,12.8,5,6
+BMW,M6 Coupee,129600,412,4395,1925,9.9,2,6
+Land Rover,Range Rover Sport SVR,129600,405,5000,2330,12.8,5,6
+BMW Alpina,B6 Bi-Turbo Coupee,129200,441,4395,1940,9.4,2,6
+Mercedes,AMG GT Roadster,129180,350,3982,1670,9.4,2,6
+Maserati,GranTurismo Sport,129020,338,4691,1880,14.3,2,6
+Aston Martin,V8 Vantage AMR,126995,320,4735,1610,13.8,3,6
+Porsche,911 Carrera Coupee,125760,331,2981,1525,9.4,2,6
+Chevrolet,Corvette Z06 Cabriolet,124700,485,6162,1734,12.7,2,6
+Land Rover,Range Rover 5.0 V8 SC,121800,375,5000,2336,12.8,5,6
+Chevrolet,Corvette Z06 Coupee,119700,485,6162,1734,12.7,3,6
+Audi,S8 cod,118500,382,3993,2050,9.4,4,6
+Porsche,911.,118382,272,2981,1645,8.9,2,6
+Mercedes,AMG GT Coupee,117280,350,3982,1615,9.3,2,6
+Porsche,911 Carrera Cabriolet,111004,272,2981,1575,8.5,2,6
+Porsche,911 Carrera T Coupee,107553,272,2981,1500,9.5,2,6
+Mercedes,G 500,106701,310,3982,2595,12.3,5,6
+Audi,A8 4.0 TFSI cod,104400,320,3993,1955,8.9,4,6
+Mercedes,S 450 Coupee,101656,270,2996,2050,8.9,2,6
+Chevrolet,Corvette Grand Sport Cabriolet 6.2 V8,100900,343,6162,1614,12.3,2,6
+Mercedes,S 400 Coupee,100561,270,2996,2035,8.3,2,6
+Cadillac,Escalade 6.2 V8,99900,313,6162,2710,12.6,5,6
+Mercedes,SL 400,99341,270,2996,1735,7.7,2,6
+Porsche,911 Carrera Coupee,97914,272,2981,1505,8.3,2,6
+Porsche,Panamera Sport Turismo 4,97557,243,2995,1955,7.8,5,6
+Maserati,Quattroporte,97430,257,2979,1860,9.1,4,6
+Chevrolet,Corvette Grand Sport Coupe 6.2 V8,95900,343,6162,1588,12.3,3,6
+Land Rover,Range Rover Sport 5.0 V8 SC,94900,375,5000,2306,12.8,5,6
+Jaguar,XJ 3.0 V6 Kompressor,93800,250,2995,1865,9.8,4,6
+BMW,740i,93000,240,2998,1800,6.8,4,6
+Mercedes,S 450,92255,270,2987,1995,6.6,4,6
+Porsche,Panamera,90655,243,2995,1890,7.5,5,6
+BMW,640i Cabrio,90600,235,2979,1895,7.7,2,6
+Chevrolet,Corvette Stingray Cabriolet 6.2 V8,85400,343,6162,1664,12.3,2,6
+BMW,640i Gran Coupe,83900,235,2979,1825,7.6,4,6
+BMW,640i Coupe,81900,235,2979,1760,7.6,2,6
+Chevrolet,Corvette Stingray Coupe 6.2 V8,80400,343,6162,1614,12.3,3,6
+Mercedes,GLS 400,77029,245,2996,2435,8.9,5,6
+Cadillac,CT6 3.0 V6,73500,307,2997,1879,9.6,4,6
+Land Rover,Range Rover Sport 2.0 Si4,65600,221,1997,2083,9.2,5,6
+Land Rover,Range Rover Evoque Coupe Si4,62200,213,1998,1833,7.6,3,3
+BMW,M2 Coupe,59500,272,2979,1570,8.5,2,3
+Mercedes,CLA 45 AMG Shooting Brake,57804,280,1991,1615,6.9,5,3
+Mercedes,CLA 45 AMG,57209,280,1991,1585,6.9,4,3
+Mercedes,GLA 45 AMG,56852,280,1991,1585,7.4,5,3
+Audi,RS3 Limousine,55900,294,2480,1590,8.3,4,3
+Land Rover,Range Rover Evoque Cabriolet Si4,55300,177,1998,2013,8.2,2,3
+Audi,RS3 Sportback,54600,294,2480,1585,8.3,5,3
+Mercedes,A 45 AMG,51527,280,1991,1555,6.9,5,3
+Audi,S3 Cabriolet,51150,228,1984,1710,6.7,2,3
+VW,Golf R Variant,45350,228,1984,1593,7.1,5,3
+Subaru,Impreza WRX STi 2.5,44500,221,2457,1527,10.9,4,3
+Land Rover,Range Rover Evoque Si4,43850,177,1998,1752,8.2,5,3
+Audi,S3 Limousine,43250,228,1984,1505,7,4,3
+Audi,S3 Sportback,42350,228,1984,1505,7,5,3
+Jaguar,E-Pace P250,42350,183,1998,1832,7.7,5,3
+Subaru,Impreza WRX STi 2.5,41550,221,2457,1575,10.4,4,3
+Audi,S3,41450,228,1984,1480,7,3,3
+VW,Golf R,41175,228,1984,1483,7.8,3,3
+Ford,Focus RS,40675,257,2261,1560,7.7,5,3
+Infiniti,QX30 2.0t,40150,155,1991,1542,6.7,5,3
+Lotus,Elise,39900,100,1598,876,6.3,2,3
+MINI,John Cooper Works Countryman,39500,170,1998,1615,7.4,5,3
+BMW,X2 sDrive20i,39200,141,1998,1535,5.5,5,3
+MINI,John Cooper Works Clubman,36800,170,1998,1550,7.4,5,3
+Opel,Astra OPC,36360,206,1998,1550,7.8,3,3
+Honda,Civic Type R,36050,235,1996,1380,7.7,5,3
+SEAT,Leon ST Cupra 300,35930,221,1984,1440,7,5,3
+Peugeot,308.,35350,200,1598,1280,6,5,3
+SEAT,Leon Cupra 300,34730,221,1984,1395,6.9,5,3
+SEAT,Leon SC Cupra 300,34340,221,1984,1375,6.9,3,3
+VW,Touran 1.2 TSI BMT,34300,81,1197,1436,5.5,5,3
+BMW,218i Cabrio,34200,100,1499,1575,5.5,2,3
+VW,Golf Alltrack 1.8 TSI BMT,34125,132,1798,1537,6.7,5,3
+Mazda,CX-5 SKYACTIV-G 160,32190,118,1998,1495,6.8,5,3
+BMW,X1 sDrive18i,31700,103,1499,1475,5.5,5,3
+Audi,A3 Cabriolet 1.4 TFSI,31450,85,1395,1430,5.3,2,3
+Volvo,XC40 T3,31350,114,1498,1725,6.8,5,3
+Ford,Focus Turnier ST 2.0 EcoBoost Start/Stopp,30550,184,1999,1461,6.8,5,3
+VW,Golf GTI,30425,169,1984,1364,6.4,3,3
+Mercedes,CLA 180 Shooting Brake,30274,90,1595,1430,5.5,5,3
+Mazda,MX-5 RF SKYACTIV-G 160,29890,118,1998,1120,6.9,2,3
+BMW,218i Coupe,29750,100,1499,1420,5.1,2,3
+Hyundai,i30 N,29700,184,1998,1475,7,5,3
+Mercedes,CLA 180,29679,90,1595,1395,5.4,4,3
+Ford,Focus ST 2.0 EcoBoost Start/Stopp,29600,184,1999,1437,6.8,5,3
+Mercedes,GLA 180,28941,90,1595,1395,5.7,5,3
+Audi,Q3 1.4 TFSI,28700,92,1395,1460,5.8,5,3
+BMW,216i Gran Tourer,28600,75,1499,1475,5.3,5,3
+Volvo,V40 Cross Country T3,28280,112,1969,1569,5.6,5,3
+BMW,216i Active Tourer,27350,75,1499,1415,5.4,5,3
+VW,Tiguan 1.4 TSI,26975,92,1395,1490,6.1,5,3
+Mercedes,B 160,26638,75,1595,1395,5.5,5,3
+Audi,A3 Limousine 1.0 TFSI,25550,85,999,1260,4.4,4,3
+Honda,Civic Limousine 1.5 Turbo,25520,134,1498,1321,5.7,4,3
+DS Automobiles,DS 4 Crossback PureTech 130 Stop&Start,25490,96,1199,1330,4.9,5,3
+KIA,pro_ceed GT,25390,150,1591,1395,7.4,3,3
+KIA,ceed GT,25390,150,1591,1382,7.4,5,3
+Fiat,124 Spider 1.4 Multiair Turbo,24990,103,1368,1125,6.4,2,3
+Fiat,124 Spider 1.4 Multiair Turbo,24990,103,1368,1125,6.4,2,3
+Hyundai,Veloster 1.6 Turbo,24990,137,1591,1333,6.9,4,3
+SEAT,Leon X-PERIENCE 1.4 TSI Start&Stop,24950,92,1395,1263,5.3,5,3
+VW,Scirocco 1.4 TSI BMT,24950,92,1395,1280,5.4,3,3
+Jeep,Compass 1.4 Multiair 140,24900,103,1368,1505,6.2,5,3
+Volvo,V40 T2,24850,90,1969,1546,5.6,5,3
+VW,Caddy Alltrack 1.2 TSI BMT,24782,62,1197,1350,6.1,5,3
+BMW,116i,24700,80,1499,1375,5.3,3,3
+Mercedes,A 160,24681,75,1595,1370,5.4,5,3
+Audi,A3 Sportback 1.0 TFSI,24650,85,999,1255,4.5,5,3
+Honda,Civic Tourer 1.8,24590,104,1798,1355,6.2,5,3
+Skoda,Karoq 1.0 TSI,24290,85,999,1340,5.1,5,3
+Infiniti,Q30 1.6t,24200,90,1595,1407,5.7,5,3
+MINI,One Countryman,24000,75,1499,1440,5.5,5,3
+DS Automobiles,DS 4 PureTech 130 Stop&Start,23990,96,1199,1330,4.9,5,3
+KIA,pro_ceed 1.0 T-GDI 120 ISG,23990,88,998,1271,4.9,3,3
+Opel,Zafira 1.4 Turbo,23950,88,1364,1628,6.8,5,3
+Audi,A3 1.0 TFSI,23750,85,999,1225,4.5,3,3
+Opel,Grandland X 1.2 DI Turbo Start&Stop,23700,96,1199,1350,5.4,5,3
+Renault,Grand Sconic ENERGY TCe 115,23690,85,1197,1505,6.1,5,3
+VW,Beetle Cabriolet 1.2 TSI BMT,23450,77,1197,1395,5.4,2,3
+Audi,Q2 1.0 TFSI ultra,23400,85,999,1280,5.1,5,3
+Ford,Kuga 1.5 EcoBoost Start/Stopp,23300,88,1498,1579,6.3,5,3
+Peugeot,3008 1.2 PureTech 130,23250,96,1199,1325,5.1,5,3
+Mazda,MX-5 SKYACTIV-G 131,22990,96,1496,1050,6,2,3
+Subaru,XV 1.6i,22980,84,1600,1408,6.4,5,3
+VW,Caddy Beach 1.2 TSI BMT,22943,62,1197,1350,6.1,5,3
+MINI,One Clubman,22850,75,1499,1375,5.1,5,3
+Hyundai,Tucson 1.6 GDI blue    ,22740,97,1591,1454,6.3,5,3
+Hyundai,i30 Fastback 1.0 T-GDI,22200,88,  998,1460,5.2,5,3
+Toyota,C-HR 1.2 T,21990,85,1197,1320,5.9,5,3
+Subaru,Impreza 1.6i,21980,84,1600,1359,6.2,5,3
+VW,Golf Variant 1.0 TSI BMT,21850,81,999,1295,4.9,5,3
+Mazda,3 SKYACTIV-G 120,21790,88,1998,1280,5.1,4,3
+Toyota,Verso 1.6,21765,97,1598,1505,6.8,5,3
+Alfa Romeo,Giulietta 1.4 TB 16V,21500,88,1368,1355,6.2,5,3
+Opel,Astra GTC 1.4 Turbo,21360,88,1364,1437,6.3,3,3
+Toyota,Corolla 1.6,21220,97,1598,1270,6,4,3
+Citroen,Grand C4 Picasso PureTech 130 Stop&Start,20990,96,1199,1370,5,5,3
+Ford,Grand C-MAX 1.0 EcoBoost Start/Stopp,20850,74,998,1493,5.2,5,3
+Nissan,Qashqai 1.2 DIG-T,20490,85,1197,1350,5.6,5,3
+VW,Golf Sportsvan 1.0 TSI,20475,63,999,1335,4.9,5,3
+VW,Golf Sportsvan 1.2 TSI BMT,20475,63,1197,1320,5,5,3
+VW,T-Roc 1.0 TSI,20390,85,999,1270,5.1,5,3
+Ford,Tourneo Connect 1.0 EcoBoost Start/Stopp,20249,74,998,1474,5.6,5,3
+Opel,Astra 1.6,20220,85,1598,1405,6.8,4,3
+Honda,Civic 1.0 Turbo,19990,95,988,1229,4.8,5,3
+KIA,Carens 1.6 GDI,19990,99,1591,1458,6.5,5,3
+KIA,Sportage 1.6 GDI,19990,97,1591,1397,6.7,5,3
+Mercedes,Citan Tourer lang 112,19990,84,1192,1440,6.2,5,3
+Renault,Sconic ENERGY TCe 115,19990,85,1197,1503,5.8,5,3
+Renault,Kadjar ENERGY TCe 130,19990,96,1197,1381,5.7,5,3
+SEAT,Ateca 1.0 TSI Ecomotive,19990,85,999,1280,5.2,5,3
+SsangYong,Korando 2.0 e-XGi 200,19990,110,1998,1612,7.5,5,3
+Subaru,XV 1.6i,19990,84,1600,1370,6.5,5,3
+Peugeot,308 SW 1.2 PureTech 110,19800,81,1199,1265,4.7,5,3
+Suzuki,SX4 S-Cross 1.0 Boosterjet,19790,82,998,1165,5,5,3
+Citroen,C4 Picasso PureTech 110 Stop&Start,18990,81,1199,1355,5.1,5,3
+Mitsubishi,ASX 1.6 ClearTec,18990,86,1590,1335,5.7,5,3
+Ford,Focus 1.0 EcoBoost Start/Stopp,18700,74,998,1303,4.8,4,3
+Peugeot,308 1.2 PureTech 110,18700,81,1199,1155,4.6,5,3
+Subaru,Impreza 1.6i,18600,84,1600,1380,6.2,5,3
+Opel,Astra Sports Tourer 1.4,18550,74,1399,1273,5.7,5,3
+VW,Caddy 1.2 TSI BMT,18528,62,1197,1350,6.1,4,3
+Mitsubishi,Lancer 1.6 ClearTec,18490,86,1590,1305,5.5,4,3
+Mitsubishi,Lancer Sportback 1.6 ClearTec,18490,86,1590,1345,5.5,5,3
+Renault,Megane Grandtour ENERGY TCe 100,18490,74,1197,1366,5.4,5,3
+Hyundai,i30 Kombi 1.4,18450,74,1368,1285,5.6,5,3
+VW,Caddy Kombi 1.2 TSI BMT,18445,62,1197,1350,6.1,4,3
+Nissan,Pulsar 1.2 DIG-T,18270,85,1197,1265,5,5,3
+Ford,C-MAX 1.6 Ti-VCT,18250,63,1596,1374,6.4,5,3
+Mazda,3 SKYACTIV-G 100,18190,74,1496,1260,5.1,5,3
+VW,Golf 1.0 TSI BMT,18075,63,999,1206,4.8,3,3
+Fiat,DoblKombi 1.4 16V,17990,70,1368,1370,7.4,5,3
+SEAT,Toledo 1.2 TSI,17990,66,1197,1156,4.7,5,3
+Citroen,Berlingo Kombi VTi 95,17850,72,1598,1395,6.4,4,3
+Peugeot,Partner Tepee VTi 98,17850,72,1598,1550,6.4,4,3
+Ford,Focus Turnier 1.6 Ti-VCT,17700,63,1596,1300,6,5,3
+Toyota,Auris Touring Sports 1.33,17690,73,1329,1250,5.6,5,3
+Opel,Astra 1.4,17550,74,1399,1244,5.5,5,3
+Renault,Megane ENERGY TCe 100,17490,74,1197,1280,5.4,5,3
+SsangYong,XLV 1.6 e-XGi 160,17490,94,1597,1390,7.1,5,3
+Hyundai,i30 1.4,17450,74,1368,1244,5.4,5,3
+Citroen,C4 PureTech 110,17240,81,1199,1275,4.8,5,3
+Renault,Kangoo ENERGY TCe 115,17150,84,1197,1395,6.2,4,3
+SEAT,Leon ST 1.2 TSI,16640,63,1197,1233,5.1,5,3
+Toyota,Auris 1.33,16490,73,1329,1225,5.5,5,3
+Fiat,Tipo Kombi 1.4 16V,16450,70,1368,1280,5.7,5,3
+Ford,Focus 1.6 Ti-VCT,16450,63,1596,1264,5.9,5,3
+KIA,ceed Sportswagon 1.4,16190,73,1368,1279,6,5,3
+Skoda,Rapid 1.0 TSI,15890,70,999,1170,4.4,5,3
+Skoda,Rapid Spaceback 1.0 TSI,15790,70,999,1165,4.4,5,3
+SEAT,Leon 1.2 TSI,15490,63,1197,1188,5.1,5,3
+Fiat,Tipo 1.4 16V,15450,70,1368,1270,5.7,5,3
+Opel,Combo Combi 1.4,15110,70,1364,1445,7.4,5,3
+SEAT,Leon SC 1.2 TSI,14990,63,1197,1168,5.1,3,3
+KIA,ceed 1.4,14490,73,1368,1254,6,5,3
+Fiat,Tipo 1.4 16V,14450,70,1368,1225,5.7,4,3
+Dacia,Lodgy Stepway TCe 115 Start&Stop,14200,85,1197,1278,5.6,5,3
+Dacia,Dokker Stepway TCe 115 Start&Stop,13600,85,1197,1280,5.7,5,3
+Citroen,C-Elysee PureTech 82,12990,60,1199,1055,4.8,4,3
+Lada,Vesta 1.6 16V,12740,78,1596,1250,6.1,4,3
+Dacia,Logan MCV Stepway TCe 90 Start&Stop,12200,66,898,1165,5.1,5,3
+Lada,Urban 1.7,11990,61,1690,1285,9.5,3,3
+Dacia,Duster SCe 115,11290,84,1598,1262,6.6,5,3
+Lada,Taiga 1.7,10790,61,1690,1285,9.5,3,3
+Dacia,Duster SCe 115 Start&Stop,10690,84,1598,1165,6.4,5,3
+Dacia,Lodgy SCe 100 Start&Stop,9990,75,1598,1211,6.1,5,3
+Dacia,Dokker SCe 100 Start&Stop,8990,75,1598,1239,6.2,4,3
+Lada,Granta 1.6 8V,8500,64,1596,1080,6.6,5,3
+Dacia,Logan MCV SCe 75,7990,54,998,1091,5.4,5,3
+Lada,Granta 1.6 8V,7260,64,1596,1080,6.6,4,3
\ No newline at end of file
diff --git a/03-numpy-und-matplotlib/folien-code/folien-code.ipynb b/03-numpy-und-matplotlib/folien-code/folien-code.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..0d69cf7377d7a679581b62e7e21ac7be2b244e9e
--- /dev/null
+++ b/03-numpy-und-matplotlib/folien-code/folien-code.ipynb
@@ -0,0 +1,436 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    " # Code zu Folien\n",
+    "\n",
+    "\n",
+    "\n",
+    " Dieses Skript bzw. Jupyter-Notebook enthält den Code, der auch auf den Folien \"NumPy & Matplotlib\" enthalten ist. Zum Vorbereiten, Mitmachen oder Nacharbeiten."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import numpy as np\n",
+    "v = np.array([1, 3, 5])\n",
+    "print(v)\n",
+    "print(v.shape, v.dtype)\n",
+    "\n",
+    "a = np.array([[1, 2, 3], [4, 5, 6]])\n",
+    "print(a)\n",
+    "print(a.shape, a.dtype)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "a = np.array([[[1]], [[3]], [[5]]])\n",
+    "print(a.shape)\n",
+    "\n",
+    "a = np.array([[[1], [3], [5]]])\n",
+    "print(a.shape)\n",
+    "\n",
+    "a = np.array([[[1, 3, 5]]])\n",
+    "print(a.shape)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "v = np.arange(6)                      # shape: (6,) Vektor\n",
+    "a = v.reshape(-1, 3)                  # shape: (2, 3) Matrix\n",
+    "b = v.reshape(1, -1)                  # shape: (1, 6) Matrix\n",
+    "# x = v.reshape(4, -1)                  # shape: (4, ?) Matrix (passt nicht)\n",
+    "c = a[np.newaxis, :, :]              # shape: (1, 2, 3) 3D\n",
+    "d = a[np.newaxis, ...]               # shape: (1, 2, 3) 3D\n",
+    "e = a[np.newaxis, :, np.newaxis, :]  # shape: (1, 2, 1, 3) 4D\n",
+    "f = e.squeeze()                      # shape: (2, 3) Matrix. Was ergäbe e.ravel()?\n",
+    "\n",
+    "print(v.shape)\n",
+    "print(a.shape)\n",
+    "print(b.shape)\n",
+    "print(c.shape)\n",
+    "print(d.shape)\n",
+    "print(e.shape)\n",
+    "print(f.shape)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "rng = np.random.default_rng()  # random number generator\n",
+    "\n",
+    "np.zeros((1, 5), dtype=bool)          # 1 x 5-Matrix mit False\n",
+    "np.zeros_like(a)                      # Array mit 0en mit Shape und Typ von a\n",
+    "np.ones((1, 3))                       # 1 x 3-Matrix mit 1en\n",
+    "rng.uniform(size=(2, 4))              # 2 x 4-Matrix mit uniformen Zufallszahlen aus [0, 1)\n",
+    "rng.integers(0, 10, (2, 4))           # 2 x 4-Matrix mit Zufallszahlen von 0 bis 9\n",
+    "rng.choice(10, size=4, replace=False) # Vektor mit 4 eindeutigen Elem. aus {0, ..., 9}\n",
+    "rng.permutation(10)                   # {0, ..., 9}, aber in zufälliger Reihenfolge\n",
+    "np.arange(-1, 0.05, 0.1)              # Vektor von -1 bis 1 mit Schrittweite 0.1\n",
+    "np.linspace(-1, 1, 9)                 # Vektor mit 9 Werten lin. zwischen -1 und 1\n",
+    "np.logspace(-1, 1, 9)                 # Vektor mit 9 Werten log. zwischen 10^-1 und 10^1\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "a = np.array([[1, 2, 3], [4, 5, 6]])\n",
+    "v = np.array([10, 20, 30])\n",
+    "b = np.ones((3, 3))\n",
+    "\n",
+    "\n",
+    "print('np.sin(a):')\n",
+    "print(np.sin(a))\n",
+    "print('np.mean(a), np.std(a), np.max(a), np.min(a):')\n",
+    "print(np.mean(a), np.std(a), np.max(a), np.min(a))\n",
+    "print('np.sum(a), np.sum(a, axis=0), np.sum(a, axis=1):')\n",
+    "print(np.sum(a), np.sum(a, axis=0), np.sum(a, axis=1))\n",
+    "print('a**2:')\n",
+    "print(a**2)\n",
+    "print('a.T:')\n",
+    "print(a.T)\n",
+    "print('a @ v:')\n",
+    "print(a @ v)\n",
+    "print('a @ b:')\n",
+    "print(a @ b)\n",
+    "print('a.reshape(6):')\n",
+    "print(a.reshape(6))\n",
+    "print('np.delete(a, 1, axis=0):')\n",
+    "print(np.delete(a, 1, axis=0))\n",
+    "print('np.sort(a):')\n",
+    "print(np.sort(a))\n",
+    "print('np.argsort(a):')\n",
+    "print(np.argsort(a))\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "v = np.array([0, 1, 2, 3, 4, 5, 6])\n",
+    "\n",
+    "print(v[1:5])   # Elemente 1 (inkl.) bis 5 (exkl.)\n",
+    "print(v[1:5:2]) # Elemente 1 bis 5 mit Schrittweite 2\n",
+    "print(v[::2])   # Alle Elemente mit Schrittweite 2\n",
+    "print(v[-3:])   # Die 3 letzten Elemente\n",
+    "print(v[::-1])  # Reihenfolge umkehren\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "a = np.array([[1,2,3], [4,5,6]])\n",
+    "\n",
+    "print(a[1, 2])    # Element a_{1,2}\n",
+    "print(a[1])       # Zeile 1\n",
+    "print(a[1, 1:])   # Zeile 1, ab Spalte 1\n",
+    "print(a[:, -1])   # letzte Spalte\n",
+    "print(a[0, ::-1]) # Zeile 0, Spalten umkehren\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "a = np.array([[1, 2, 3], [4, 5, 6]])\n",
+    "b = a[0, ::-1]    # a und b zeigen auf die gleichen Daten.\n",
+    "b[0] = 0          # Eine Änderung in b ...\n",
+    "print(a)          # ... wirkt sich auch auf a aus.\n",
+    "\n",
+    "c = a.copy()\n",
+    "print(np.shares_memory(a, b))\n",
+    "print(np.shares_memory(a, c))\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "v = np.array([4, 8, 15, 16, 23, 42])\n",
+    "\n",
+    "print(v[[1, 4, 2]])  # Die Elemente bei 1, 4 und 2 als neues np-Array\n",
+    "\n",
+    "print(v[np.array([[1, 4],\n",
+    "                  [1, 2]])])\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "A = np.array([[1,  2,  3,  4],\n",
+    "              [5,  6,  7,  8],\n",
+    "              [9, 10, 11, 12]])\n",
+    "\n",
+    "# Die Indizes werden paarweise genommen: [1, 1] und [2, 3]\n",
+    "print(A[[1, 2],\n",
+    "        [1, 3]])\n",
+    "\n",
+    "# Zeilen 1 und 2, Spalten 1 und 3)\n",
+    "print(A[np.ix_([1, 2], [1, 3])])\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "a = np.array([[1, 2, 3], [4, 5, 6]])\n",
+    "\n",
+    "i = a > 4\n",
+    "print(i)\n",
+    "print(a[i])\n",
+    "\n",
+    "a[~i] += 10   # ~ invertiert die Boolesche Matrix\n",
+    "print(a)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "idx2d = np.nonzero(i)      # Trues bei Zeile 1, Spalte 1 und bei Zeile 1, Spalte 2\n",
+    "print(idx2d)\n",
+    "print(a[idx2d])\n",
+    "\n",
+    "idx1d = np.flatnonzero(i)  # Trues bei Einzelindex 4 und bei Einzelindex 5\n",
+    "print(idx1d)\n",
+    "print(a.flat[idx1d])\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "\n",
+    "data = np.random.default_rng().random(100)  # uniform verteilt in [0, 1)\n",
+    "print(np.sum(data > 0.5))\n",
+    "print(np.count_nonzero(data > 0.5))\n",
+    "print(len(data[data > 0.5]))\n",
+    "print(np.nonzero(data > 0.5)[0].size)  # [0] weil mit Tupel umhüllt\n",
+    "print(np.flatnonzero(data > 0.5).size) # size ist Produkt über #*shape*\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "A = np.array([[0, 1],\n",
+    "              [2, 3],\n",
+    "              [4, 5]])\n",
+    "\n",
+    "B = np.array([[5],\n",
+    "              [7],\n",
+    "              [9]])\n",
+    "\n",
+    "C = np.array([[8, 7],\n",
+    "              [9, 6]])\n",
+    "\n",
+    "V = np.vstack((A, C))\n",
+    "print(V)\n",
+    "\n",
+    "H = np.hstack((A, B, B))\n",
+    "print(H)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "data = np.loadtxt('autos.csv', delimiter=',', skiprows=1, usecols=range(2,9))\n",
+    "print(data)\n",
+    "print(data.shape)\n",
+    "\n",
+    "# usecols als Zahlen oder Namen (z. B. 'Hubraum') möglich!\n",
+    "sa = np.genfromtxt('autos.csv', delimiter=',', names=True, dtype=float)\n",
+    "data = sa.view((float, len(sa.dtype.names)))\n",
+    "print(data)\n",
+    "print(data.shape)\n",
+    "\n",
+    "structdata = np.genfromtxt('autos.csv', delimiter=',', names=True, dtype=None, encoding='utf-8')\n",
+    "print(structdata)\n",
+    "print(structdata.shape)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "x = np.arange(0, 10, 0.2)\n",
+    "y1 = np.sin(x); y2 = np.cos(x)\n",
+    "\n",
+    "import matplotlib.pyplot as plt\n",
+    "fig, ax = plt.subplots()    # neues Fenster mit Achsen\n",
+    "ax.plot(x, y1, label='Sin') # sin Plot hinzufügen\n",
+    "ax.plot(x, y2, label='Cos') # cos Plot hinzufügen\n",
+    "\n",
+    "ax.set_title('Simple Plot')\n",
+    "ax.set_xlabel('x-Achse')\n",
+    "ax.set_ylabel('y-Achse')\n",
+    "ax.grid()\n",
+    "plt.legend()\n",
+    "fig.savefig('plot.pdf', bbox_inches='tight') # ggf. Plot speichern (pdf, png, ...)\n",
+    "plt.show()                                   # anzeigen (bei non-interactive)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "rng = np.random.default_rng()\n",
+    "x = rng.random(100)\n",
+    "y = 5 * x**2 + rng.random(100)\n",
+    "plt.figure()   # neues Fenster (optional)\n",
+    "plt.scatter(x, y, s=100*y, c=x, alpha=0.4)\n",
+    "\n",
+    "fig = plt.gcf()\n",
+    "ax = plt.gca()\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from numpy.polynomial import Polynomial\n",
+    "\n",
+    "x = np.arange(10)\n",
+    "y = 2 * x\n",
+    "# y = x ** 2\n",
+    "\n",
+    "p = Polynomial.fit(x, y, deg=1).convert()\n",
+    "\n",
+    "print(p(1))\n",
+    "print(p(np.array([1., 3., 5.])))\n",
+    "print(p.coef)      # Koeffizienten\n",
+    "\n",
+    "plt.plot(x, p(x))   # Plot oben\n",
+    "plt.scatter(x, y, color='r')\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from sklearn.linear_model import LinearRegression\n",
+    "\n",
+    "x = np.arange(10).reshape(-1, 1)\n",
+    "y = x ** 2\n",
+    "\n",
+    "linreg = LinearRegression()\n",
+    "linreg.fit(x, y)\n",
+    "\n",
+    "print(linreg.predict([[1]]))\n",
+    "print(linreg.predict([[1], [3], [5]]))\n",
+    "print(linreg.intercept_, linreg.coef_)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "\n",
+    "x = np.arange(10).reshape(-1, 1)\n",
+    "y = x ** 2\n",
+    "\n",
+    "x_poly = np.hstack((x, x**2)) # shape: 10 x 2\n",
+    "\n",
+    "linreg = LinearRegression()\n",
+    "linreg.fit(x_poly, y)\n",
+    "\n",
+    "print(linreg.predict([[3, 9]]))\n",
+    "\n",
+    "print(linreg.intercept_, linreg.coef_)\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "rng = np.random.default_rng()\n",
+    "x = rng.uniform(size=(100, 1)) * 3 - 0.5\n",
+    "y = np.round(x % 1) - 0.5\n",
+    "\n",
+    "def fourier_basis(x, n=4):\n",
+    "    return np.hstack([np.sin(2 * np.pi * k * x) for k in range(1, 2 * n, 2)])\n",
+    "\n",
+    "x_f = fourier_basis(x, 5)\n",
+    "linreg = LinearRegression()\n",
+    "linreg.fit(x_f, y)\n",
+    "\n",
+    "x_plt = np.linspace(0, 4, 501).reshape(-1, 1)\n",
+    "x_plt_f = fourier_basis(x_plt, 5)\n",
+    "y_plt = linreg.predict(x_plt_f)\n",
+    "\n",
+    "plt.plot(x_plt, y_plt)\n",
+    "plt.scatter(x, y, color='r')\n"
+   ]
+  }
+ ],
+ "metadata": {
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": 3
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/03-numpy-und-matplotlib/folien-code/folien-code.py b/03-numpy-und-matplotlib/folien-code/folien-code.py
new file mode 100644
index 0000000000000000000000000000000000000000..303c74a9bf04b1cf85923aca7dfe1f529aa39ab6
--- /dev/null
+++ b/03-numpy-und-matplotlib/folien-code/folien-code.py
@@ -0,0 +1,283 @@
+# %% [markdown]
+# # Code zu Folien
+#
+# Dieses Skript bzw. Jupyter-Notebook enthält den Code, der auch auf den Folien "NumPy & Matplotlib" enthalten ist. Zum Vorbereiten, Mitmachen oder Nacharbeiten.
+
+# %% 1D und 2D Arrays
+import numpy as np
+v = np.array([1, 3, 5])
+print(v)
+print(v.shape, v.dtype)
+
+a = np.array([[1, 2, 3], [4, 5, 6]])
+print(a)
+print(a.shape, a.dtype)
+
+# %% 3D Arrays
+a = np.array([[[1]], [[3]], [[5]]])
+print(a.shape)
+
+a = np.array([[[1], [3], [5]]])
+print(a.shape)
+
+a = np.array([[[1, 3, 5]]])
+print(a.shape)
+
+# %% Shape
+v = np.arange(6)                      # shape: (6,) Vektor
+a = v.reshape(-1, 3)                  # shape: (2, 3) Matrix
+b = v.reshape(1, -1)                  # shape: (1, 6) Matrix
+# x = v.reshape(4, -1)                  # shape: (4, ?) Matrix (passt nicht)
+c = a[np.newaxis, :, :]              # shape: (1, 2, 3) 3D
+d = a[np.newaxis, ...]               # shape: (1, 2, 3) 3D
+e = a[np.newaxis, :, np.newaxis, :]  # shape: (1, 2, 1, 3) 4D
+f = e.squeeze()                      # shape: (2, 3) Matrix. Was ergäbe e.ravel()?
+
+print(v.shape)
+print(a.shape)
+print(b.shape)
+print(c.shape)
+print(d.shape)
+print(e.shape)
+print(f.shape)
+
+# %% Erzeugendenfunktionen
+rng = np.random.default_rng()  # random number generator
+
+np.zeros((1, 5), dtype=bool)          # 1 x 5-Matrix mit False
+np.zeros_like(a)                      # Array mit 0en mit Shape und Typ von a
+np.ones((1, 3))                       # 1 x 3-Matrix mit 1en
+rng.uniform(size=(2, 4))              # 2 x 4-Matrix mit uniformen Zufallszahlen aus [0, 1)
+rng.integers(0, 10, (2, 4))           # 2 x 4-Matrix mit Zufallszahlen von 0 bis 9
+rng.choice(10, size=4, replace=False) # Vektor mit 4 eindeutigen Elem. aus {0, ..., 9}
+rng.permutation(10)                   # {0, ..., 9}, aber in zufälliger Reihenfolge
+np.arange(-1, 0.05, 0.1)              # Vektor von -1 bis 1 mit Schrittweite 0.1
+np.linspace(-1, 1, 9)                 # Vektor mit 9 Werten lin. zwischen -1 und 1
+np.logspace(-1, 1, 9)                 # Vektor mit 9 Werten log. zwischen 10^-1 und 10^1
+
+# %% Rechnen
+a = np.array([[1, 2, 3], [4, 5, 6]])
+v = np.array([10, 20, 30])
+b = np.ones((3, 3))
+
+
+print('np.sin(a):')
+print(np.sin(a))
+print('np.mean(a), np.std(a), np.max(a), np.min(a):')
+print(np.mean(a), np.std(a), np.max(a), np.min(a))
+print('np.sum(a), np.sum(a, axis=0), np.sum(a, axis=1):')
+print(np.sum(a), np.sum(a, axis=0), np.sum(a, axis=1))
+print('a**2:')
+print(a**2)
+print('a.T:')
+print(a.T)
+print('a @ v:')
+print(a @ v)
+print('a @ b:')
+print(a @ b)
+print('a.reshape(6):')
+print(a.reshape(6))
+print('np.delete(a, 1, axis=0):')
+print(np.delete(a, 1, axis=0))
+print('np.sort(a):')
+print(np.sort(a))
+print('np.argsort(a):')
+print(np.argsort(a))
+
+# %% Indizierung & Slicing: v
+v = np.array([0, 1, 2, 3, 4, 5, 6])
+
+print(v[1:5])   # Elemente 1 (inkl.) bis 5 (exkl.)
+print(v[1:5:2]) # Elemente 1 bis 5 mit Schrittweite 2
+print(v[::2])   # Alle Elemente mit Schrittweite 2
+print(v[-3:])   # Die 3 letzten Elemente
+print(v[::-1])  # Reihenfolge umkehren
+
+# %% Indizierung & Slicing: a
+a = np.array([[1,2,3], [4,5,6]])
+
+print(a[1, 2])    # Element a_{1,2}
+print(a[1])       # Zeile 1
+print(a[1, 1:])   # Zeile 1, ab Spalte 1
+print(a[:, -1])   # letzte Spalte
+print(a[0, ::-1]) # Zeile 0, Spalten umkehren
+
+# %% View
+a = np.array([[1, 2, 3], [4, 5, 6]])
+b = a[0, ::-1]    # a und b zeigen auf die gleichen Daten.
+b[0] = 0          # Eine Änderung in b ...
+print(a)          # ... wirkt sich auch auf a aus.
+
+c = a.copy()
+print(np.shares_memory(a, b))
+print(np.shares_memory(a, c))
+
+# %% Komplexe Indizierung
+v = np.array([4, 8, 15, 16, 23, 42])
+
+print(v[[1, 4, 2]])  # Die Elemente bei 1, 4 und 2 als neues np-Array
+
+print(v[np.array([[1, 4],
+                  [1, 2]])])
+
+# %% Komplexe Indizierung in 2D
+A = np.array([[1,  2,  3,  4],
+              [5,  6,  7,  8],
+              [9, 10, 11, 12]])
+
+# Die Indizes werden paarweise genommen: [1, 1] und [2, 3]
+print(A[[1, 2],
+        [1, 3]])
+
+# Zeilen 1 und 2, Spalten 1 und 3)
+print(A[np.ix_([1, 2], [1, 3])])
+
+# %% Boolesche Indizierung
+a = np.array([[1, 2, 3], [4, 5, 6]])
+
+i = a > 4
+print(i)
+print(a[i])
+
+a[~i] += 10   # ~ invertiert die Boolesche Matrix
+print(a)
+
+# %% Boolescher Index zu komplexen Index
+idx2d = np.nonzero(i)      # Trues bei Zeile 1, Spalte 1 und bei Zeile 1, Spalte 2
+print(idx2d)
+print(a[idx2d])
+
+idx1d = np.flatnonzero(i)  # Trues bei Einzelindex 4 und bei Einzelindex 5
+print(idx1d)
+print(a.flat[idx1d])
+
+# %% Beispiel: Boolesches Array
+
+data = np.random.default_rng().random(100)  # uniform verteilt in [0, 1)
+print(np.sum(data > 0.5))
+print(np.count_nonzero(data > 0.5))
+print(len(data[data > 0.5]))
+print(np.nonzero(data > 0.5)[0].size)  # [0] weil mit Tupel umhüllt
+print(np.flatnonzero(data > 0.5).size) # size ist Produkt über #*shape*
+
+# %% Arrays verbinden
+A = np.array([[0, 1],
+              [2, 3],
+              [4, 5]])
+
+B = np.array([[5],
+              [7],
+              [9]])
+
+C = np.array([[8, 7],
+              [9, 6]])
+
+V = np.vstack((A, C))
+print(V)
+
+H = np.hstack((A, B, B))
+print(H)
+
+# %% CSV-Import
+data = np.loadtxt('autos.csv', delimiter=',', skiprows=1, usecols=range(2,9))
+print(data)
+print(data.shape)
+
+# usecols als Zahlen oder Namen (z. B. 'Hubraum') möglich!
+sa = np.genfromtxt('autos.csv', delimiter=',', names=True, dtype=float)
+data = sa.view((float, len(sa.dtype.names)))
+print(data)
+print(data.shape)
+
+structdata = np.genfromtxt('autos.csv', delimiter=',', names=True, dtype=None, encoding='utf-8')
+print(structdata)
+print(structdata.shape)
+
+# %% Linienplot
+x = np.arange(0, 10, 0.2)
+y1 = np.sin(x); y2 = np.cos(x)
+
+import matplotlib.pyplot as plt
+fig, ax = plt.subplots()    # neues Fenster mit Achsen
+ax.plot(x, y1, label='Sin') # sin Plot hinzufügen
+ax.plot(x, y2, label='Cos') # cos Plot hinzufügen
+
+ax.set_title('Simple Plot')
+ax.set_xlabel('x-Achse')
+ax.set_ylabel('y-Achse')
+ax.grid()
+plt.legend()
+fig.savefig('plot.pdf', bbox_inches='tight') # ggf. Plot speichern (pdf, png, ...)
+plt.show()                                   # anzeigen (bei non-interactive)
+
+# %% Scatter Plot
+rng = np.random.default_rng()
+x = rng.random(100)
+y = 5 * x**2 + rng.random(100)
+plt.figure()   # neues Fenster (optional)
+plt.scatter(x, y, s=100*y, c=x, alpha=0.4)
+
+fig = plt.gcf()
+ax = plt.gca()
+
+# %% Lineare Regression mit NumPy
+from numpy.polynomial import Polynomial
+
+x = np.arange(10)
+y = 2 * x
+# y = x ** 2
+
+p = Polynomial.fit(x, y, deg=1).convert()
+
+print(p(1))
+print(p(np.array([1., 3., 5.])))
+print(p.coef)      # Koeffizienten
+
+plt.plot(x, p(x))   # Plot oben
+plt.scatter(x, y, color='r')
+
+# %% Lineare Regression mit Scikit-Learn, Grad 1
+from sklearn.linear_model import LinearRegression
+
+x = np.arange(10).reshape(-1, 1)
+y = x ** 2
+
+linreg = LinearRegression()
+linreg.fit(x, y)
+
+print(linreg.predict([[1]]))
+print(linreg.predict([[1], [3], [5]]))
+print(linreg.intercept_, linreg.coef_)
+
+# %% Lineare Regression mit Scikit-Learn, Grad 2
+
+x = np.arange(10).reshape(-1, 1)
+y = x ** 2
+
+x_poly = np.hstack((x, x**2)) # shape: 10 x 2
+
+linreg = LinearRegression()
+linreg.fit(x_poly, y)
+
+print(linreg.predict([[3, 9]]))
+
+print(linreg.intercept_, linreg.coef_)
+
+# %% Andere Basisfunktionen
+rng = np.random.default_rng()
+x = rng.uniform(size=(100, 1)) * 3 - 0.5
+y = np.round(x % 1) - 0.5
+
+def fourier_basis(x, n=4):
+    return np.hstack([np.sin(2 * np.pi * k * x) for k in range(1, 2 * n, 2)])
+
+x_f = fourier_basis(x, 5)
+linreg = LinearRegression()
+linreg.fit(x_f, y)
+
+x_plt = np.linspace(0, 4, 501).reshape(-1, 1)
+x_plt_f = fourier_basis(x_plt, 5)
+y_plt = linreg.predict(x_plt_f)
+
+plt.plot(x_plt, y_plt)
+plt.scatter(x, y, color='r')